blob: 13191bb9429c93e7118762dc1c1f035cc88d0596 [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 Tao0b703772023-01-26 17:19:49 +110088// c698d81b4d6868f3c5e26d2d7c3b39fe97209ec0 committed on 2023-01-26.
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 Tao0b703772023-01-26 17:19:49 +110093#define WUFFS_VERSION_PRE_RELEASE_LABEL ""
94#define WUFFS_VERSION_BUILD_METADATA_COMMIT_COUNT 3374
95#define WUFFS_VERSION_BUILD_METADATA_COMMIT_DATE 20230126
96#define WUFFS_VERSION_STRING "0.3.0+3374.20230126"
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
Nigel Taoebbecaa2022-01-08 14:08:27 +1100690// Quite OK Image.
691#define WUFFS_BASE__FOURCC__QOI 0x514F4920
692
Nigel Taoe360a532021-04-05 22:47:03 +1000693// Random Access Compression.
694#define WUFFS_BASE__FOURCC__RAC 0x52414320
695
696// Raw.
697#define WUFFS_BASE__FOURCC__RAW 0x52415720
698
699// Resource Interchange File Format.
700#define WUFFS_BASE__FOURCC__RIFF 0x52494646
701
702// Riegeli Records.
703#define WUFFS_BASE__FOURCC__RIGL 0x5249474C
704
705// Snappy.
706#define WUFFS_BASE__FOURCC__SNPY 0x534E5059
707
Nigel Taobf9dab32021-11-18 19:19:55 +1100708// Standard Red Green Blue (Rendering Intent).
709#define WUFFS_BASE__FOURCC__SRGB 0x53524742
710
Nigel Taoe360a532021-04-05 22:47:03 +1000711// Scalable Vector Graphics.
712#define WUFFS_BASE__FOURCC__SVG 0x53564720
713
714// Tape Archive.
715#define WUFFS_BASE__FOURCC__TAR 0x54415220
716
Nigel Taobf9dab32021-11-18 19:19:55 +1100717// Text.
718#define WUFFS_BASE__FOURCC__TEXT 0x54455854
719
Nigel Taocc74cb42022-01-19 11:06:15 +1100720// Truevision Advanced Raster Graphics Adapter.
721#define WUFFS_BASE__FOURCC__TGA 0x54474120
722
Nigel Taoe360a532021-04-05 22:47:03 +1000723// Tagged Image File Format.
724#define WUFFS_BASE__FOURCC__TIFF 0x54494646
725
726// Tom's Obvious Minimal Language.
727#define WUFFS_BASE__FOURCC__TOML 0x544F4D4C
728
729// Waveform.
730#define WUFFS_BASE__FOURCC__WAVE 0x57415645
731
732// Wireless Bitmap.
733#define WUFFS_BASE__FOURCC__WBMP 0x57424D50
734
Nigel Taoebbecaa2022-01-08 14:08:27 +1100735// Web Picture.
736#define WUFFS_BASE__FOURCC__WEBP 0x57454250
737
Nigel Taoe360a532021-04-05 22:47:03 +1000738// Web Open Font Format.
739#define WUFFS_BASE__FOURCC__WOFF 0x574F4646
740
Nigel Taoe360a532021-04-05 22:47:03 +1000741// Extensible Markup Language.
742#define WUFFS_BASE__FOURCC__XML 0x584D4C20
743
744// Extensible Metadata Platform.
745#define WUFFS_BASE__FOURCC__XMP 0x584D5020
746
747// Xz.
748#define WUFFS_BASE__FOURCC__XZ 0x585A2020
749
750// Zip.
751#define WUFFS_BASE__FOURCC__ZIP 0x5A495020
752
753// Zlib.
754#define WUFFS_BASE__FOURCC__ZLIB 0x5A4C4942
755
756// Zstandard.
757#define WUFFS_BASE__FOURCC__ZSTD 0x5A535444
758
759// --------
760
761// Quirks.
762
763#define WUFFS_BASE__QUIRK_IGNORE_CHECKSUM 1
764
765// --------
766
767// Flicks are a unit of time. One flick (frame-tick) is 1 / 705_600_000 of a
768// second. See https://github.com/OculusVR/Flicks
769typedef int64_t wuffs_base__flicks;
770
771#define WUFFS_BASE__FLICKS_PER_SECOND ((uint64_t)705600000)
772#define WUFFS_BASE__FLICKS_PER_MILLISECOND ((uint64_t)705600)
773
774// ---------------- Numeric Types
775
776// The helpers below are functions, instead of macros, because their arguments
777// can be an expression that we shouldn't evaluate more than once.
778//
779// They are static, so that linking multiple wuffs .o files won't complain about
780// duplicate function definitions.
781//
782// They are explicitly marked inline, even if modern compilers don't use the
783// inline attribute to guide optimizations such as inlining, to avoid the
784// -Wunused-function warning, and we like to compile with -Wall -Werror.
785
786static inline int8_t //
787wuffs_base__i8__min(int8_t x, int8_t y) {
788 return x < y ? x : y;
789}
790
791static inline int8_t //
792wuffs_base__i8__max(int8_t x, int8_t y) {
793 return x > y ? x : y;
794}
795
796static inline int16_t //
797wuffs_base__i16__min(int16_t x, int16_t y) {
798 return x < y ? x : y;
799}
800
801static inline int16_t //
802wuffs_base__i16__max(int16_t x, int16_t y) {
803 return x > y ? x : y;
804}
805
806static inline int32_t //
807wuffs_base__i32__min(int32_t x, int32_t y) {
808 return x < y ? x : y;
809}
810
811static inline int32_t //
812wuffs_base__i32__max(int32_t x, int32_t y) {
813 return x > y ? x : y;
814}
815
816static inline int64_t //
817wuffs_base__i64__min(int64_t x, int64_t y) {
818 return x < y ? x : y;
819}
820
821static inline int64_t //
822wuffs_base__i64__max(int64_t x, int64_t y) {
823 return x > y ? x : y;
824}
825
826static inline uint8_t //
827wuffs_base__u8__min(uint8_t x, uint8_t y) {
828 return x < y ? x : y;
829}
830
831static inline uint8_t //
832wuffs_base__u8__max(uint8_t x, uint8_t y) {
833 return x > y ? x : y;
834}
835
836static inline uint16_t //
837wuffs_base__u16__min(uint16_t x, uint16_t y) {
838 return x < y ? x : y;
839}
840
841static inline uint16_t //
842wuffs_base__u16__max(uint16_t x, uint16_t y) {
843 return x > y ? x : y;
844}
845
846static inline uint32_t //
847wuffs_base__u32__min(uint32_t x, uint32_t y) {
848 return x < y ? x : y;
849}
850
851static inline uint32_t //
852wuffs_base__u32__max(uint32_t x, uint32_t y) {
853 return x > y ? x : y;
854}
855
856static inline uint64_t //
857wuffs_base__u64__min(uint64_t x, uint64_t y) {
858 return x < y ? x : y;
859}
860
861static inline uint64_t //
862wuffs_base__u64__max(uint64_t x, uint64_t y) {
863 return x > y ? x : y;
864}
865
866// --------
867
Nigel Taof3caaea2021-06-28 10:12:04 +1000868static inline uint8_t //
869wuffs_base__u8__rotate_left(uint8_t x, uint32_t n) {
870 n &= 7;
871 return ((uint8_t)(x << n)) | ((uint8_t)(x >> (8 - n)));
872}
873
874static inline uint8_t //
875wuffs_base__u8__rotate_right(uint8_t x, uint32_t n) {
876 n &= 7;
877 return ((uint8_t)(x >> n)) | ((uint8_t)(x << (8 - n)));
878}
879
880static inline uint16_t //
881wuffs_base__u16__rotate_left(uint16_t x, uint32_t n) {
882 n &= 15;
883 return ((uint16_t)(x << n)) | ((uint16_t)(x >> (16 - n)));
884}
885
886static inline uint16_t //
887wuffs_base__u16__rotate_right(uint16_t x, uint32_t n) {
888 n &= 15;
889 return ((uint16_t)(x >> n)) | ((uint16_t)(x << (16 - n)));
890}
891
892static inline uint32_t //
893wuffs_base__u32__rotate_left(uint32_t x, uint32_t n) {
894 n &= 31;
895 return ((uint32_t)(x << n)) | ((uint32_t)(x >> (32 - n)));
896}
897
898static inline uint32_t //
899wuffs_base__u32__rotate_right(uint32_t x, uint32_t n) {
900 n &= 31;
901 return ((uint32_t)(x >> n)) | ((uint32_t)(x << (32 - n)));
902}
903
904static inline uint64_t //
905wuffs_base__u64__rotate_left(uint64_t x, uint32_t n) {
906 n &= 63;
907 return ((uint64_t)(x << n)) | ((uint64_t)(x >> (64 - n)));
908}
909
910static inline uint64_t //
911wuffs_base__u64__rotate_right(uint64_t x, uint32_t n) {
912 n &= 63;
913 return ((uint64_t)(x >> n)) | ((uint64_t)(x << (64 - n)));
914}
915
916// --------
917
Nigel Taoe360a532021-04-05 22:47:03 +1000918// Saturating arithmetic (sat_add, sat_sub) branchless bit-twiddling algorithms
919// are per https://locklessinc.com/articles/sat_arithmetic/
920//
921// It is important that the underlying types are unsigned integers, as signed
922// integer arithmetic overflow is undefined behavior in C.
923
924static inline uint8_t //
925wuffs_base__u8__sat_add(uint8_t x, uint8_t y) {
926 uint8_t res = (uint8_t)(x + y);
927 res |= (uint8_t)(-(res < x));
928 return res;
929}
930
931static inline uint8_t //
932wuffs_base__u8__sat_sub(uint8_t x, uint8_t y) {
933 uint8_t res = (uint8_t)(x - y);
934 res &= (uint8_t)(-(res <= x));
935 return res;
936}
937
938static inline uint16_t //
939wuffs_base__u16__sat_add(uint16_t x, uint16_t y) {
940 uint16_t res = (uint16_t)(x + y);
941 res |= (uint16_t)(-(res < x));
942 return res;
943}
944
945static inline uint16_t //
946wuffs_base__u16__sat_sub(uint16_t x, uint16_t y) {
947 uint16_t res = (uint16_t)(x - y);
948 res &= (uint16_t)(-(res <= x));
949 return res;
950}
951
952static inline uint32_t //
953wuffs_base__u32__sat_add(uint32_t x, uint32_t y) {
954 uint32_t res = (uint32_t)(x + y);
955 res |= (uint32_t)(-(res < x));
956 return res;
957}
958
959static inline uint32_t //
960wuffs_base__u32__sat_sub(uint32_t x, uint32_t y) {
961 uint32_t res = (uint32_t)(x - y);
962 res &= (uint32_t)(-(res <= x));
963 return res;
964}
965
966static inline uint64_t //
967wuffs_base__u64__sat_add(uint64_t x, uint64_t y) {
968 uint64_t res = (uint64_t)(x + y);
969 res |= (uint64_t)(-(res < x));
970 return res;
971}
972
973static inline uint64_t //
974wuffs_base__u64__sat_sub(uint64_t x, uint64_t y) {
975 uint64_t res = (uint64_t)(x - y);
976 res &= (uint64_t)(-(res <= x));
977 return res;
978}
979
980// --------
981
982typedef struct wuffs_base__multiply_u64__output__struct {
983 uint64_t lo;
984 uint64_t hi;
985} wuffs_base__multiply_u64__output;
986
987// wuffs_base__multiply_u64 returns x*y as a 128-bit value.
988//
989// The maximum inclusive output hi_lo is 0xFFFFFFFFFFFFFFFE_0000000000000001.
990static inline wuffs_base__multiply_u64__output //
991wuffs_base__multiply_u64(uint64_t x, uint64_t y) {
992#if defined(__SIZEOF_INT128__)
993 __uint128_t z = ((__uint128_t)x) * ((__uint128_t)y);
994 wuffs_base__multiply_u64__output o;
995 o.lo = ((uint64_t)(z));
996 o.hi = ((uint64_t)(z >> 64));
997 return o;
998#else
999 // TODO: consider using the _mul128 intrinsic if defined(_MSC_VER).
1000 uint64_t x0 = x & 0xFFFFFFFF;
1001 uint64_t x1 = x >> 32;
1002 uint64_t y0 = y & 0xFFFFFFFF;
1003 uint64_t y1 = y >> 32;
1004 uint64_t w0 = x0 * y0;
1005 uint64_t t = (x1 * y0) + (w0 >> 32);
1006 uint64_t w1 = t & 0xFFFFFFFF;
1007 uint64_t w2 = t >> 32;
1008 w1 += x0 * y1;
1009 wuffs_base__multiply_u64__output o;
1010 o.lo = x * y;
1011 o.hi = (x1 * y1) + w2 + (w1 >> 32);
1012 return o;
1013#endif
1014}
1015
1016// --------
1017
Nigel Taobf9dab32021-11-18 19:19:55 +11001018// The "defined(__clang__)" isn't redundant. While vanilla clang defines
1019// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
1020#if (defined(__GNUC__) || defined(__clang__)) && (__SIZEOF_LONG__ == 8)
Nigel Taoe360a532021-04-05 22:47:03 +10001021
1022static inline uint32_t //
1023wuffs_base__count_leading_zeroes_u64(uint64_t u) {
1024 return u ? ((uint32_t)(__builtin_clzl(u))) : 64u;
1025}
1026
1027#else
1028// TODO: consider using the _BitScanReverse intrinsic if defined(_MSC_VER).
1029
1030static inline uint32_t //
1031wuffs_base__count_leading_zeroes_u64(uint64_t u) {
1032 if (u == 0) {
1033 return 64;
1034 }
1035
1036 uint32_t n = 0;
1037 if ((u >> 32) == 0) {
1038 n |= 32;
1039 u <<= 32;
1040 }
1041 if ((u >> 48) == 0) {
1042 n |= 16;
1043 u <<= 16;
1044 }
1045 if ((u >> 56) == 0) {
1046 n |= 8;
1047 u <<= 8;
1048 }
1049 if ((u >> 60) == 0) {
1050 n |= 4;
1051 u <<= 4;
1052 }
1053 if ((u >> 62) == 0) {
1054 n |= 2;
1055 u <<= 2;
1056 }
1057 if ((u >> 63) == 0) {
1058 n |= 1;
1059 u <<= 1;
1060 }
1061 return n;
1062}
1063
Nigel Taobf9dab32021-11-18 19:19:55 +11001064#endif // (defined(__GNUC__) || defined(__clang__)) && (__SIZEOF_LONG__ == 8)
Nigel Taoe360a532021-04-05 22:47:03 +10001065
1066// --------
1067
Nigel Taoa8205c22022-07-10 16:01:15 +10001068// Normally, the wuffs_base__peek_etc and wuffs_base__poke_etc implementations
1069// are both (1) correct regardless of CPU endianness and (2) very fast (e.g. an
1070// inlined wuffs_base__peek_u32le__no_bounds_check call, in an optimized clang
1071// or gcc build, is a single MOV instruction on x86_64).
1072//
1073// However, the endian-agnostic implementations are slow on Microsoft's C
1074// compiler (MSC). Alternative memcpy-based implementations restore speed, but
1075// they are only correct on little-endian CPU architectures. Defining
1076// WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE opts in to these implementations.
1077//
1078// https://godbolt.org/z/q4MfjzTPh
1079#if defined(_MSC_VER) && !defined(__clang__) && \
1080 (defined(_M_ARM64) || defined(_M_X64))
1081#define WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE
1082#endif
1083
Nigel Taoe360a532021-04-05 22:47:03 +10001084#define wuffs_base__peek_u8be__no_bounds_check \
1085 wuffs_base__peek_u8__no_bounds_check
1086#define wuffs_base__peek_u8le__no_bounds_check \
1087 wuffs_base__peek_u8__no_bounds_check
1088
1089static inline uint8_t //
1090wuffs_base__peek_u8__no_bounds_check(const uint8_t* p) {
1091 return p[0];
1092}
1093
1094static inline uint16_t //
1095wuffs_base__peek_u16be__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001096#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1097 uint16_t x;
1098 memcpy(&x, p, 2);
1099 return _byteswap_ushort(x);
1100#else
Nigel Taoe360a532021-04-05 22:47:03 +10001101 return (uint16_t)(((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0));
Nigel Taoa8205c22022-07-10 16:01:15 +10001102#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001103}
1104
1105static inline uint16_t //
1106wuffs_base__peek_u16le__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001107#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1108 uint16_t x;
1109 memcpy(&x, p, 2);
1110 return x;
1111#else
Nigel Taoe360a532021-04-05 22:47:03 +10001112 return (uint16_t)(((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8));
Nigel Taoa8205c22022-07-10 16:01:15 +10001113#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001114}
1115
1116static inline uint32_t //
1117wuffs_base__peek_u24be__no_bounds_check(const uint8_t* p) {
1118 return ((uint32_t)(p[0]) << 16) | ((uint32_t)(p[1]) << 8) |
1119 ((uint32_t)(p[2]) << 0);
1120}
1121
1122static inline uint32_t //
1123wuffs_base__peek_u24le__no_bounds_check(const uint8_t* p) {
1124 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
1125 ((uint32_t)(p[2]) << 16);
1126}
1127
1128static inline uint32_t //
1129wuffs_base__peek_u32be__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001130#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1131 uint32_t x;
1132 memcpy(&x, p, 4);
1133 return _byteswap_ulong(x);
1134#else
Nigel Taoe360a532021-04-05 22:47:03 +10001135 return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) |
1136 ((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0);
Nigel Taoa8205c22022-07-10 16:01:15 +10001137#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001138}
1139
1140static inline uint32_t //
1141wuffs_base__peek_u32le__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001142#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1143 uint32_t x;
1144 memcpy(&x, p, 4);
1145 return x;
1146#else
Nigel Taoe360a532021-04-05 22:47:03 +10001147 return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) |
1148 ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24);
Nigel Taoa8205c22022-07-10 16:01:15 +10001149#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001150}
1151
1152static inline uint64_t //
1153wuffs_base__peek_u40be__no_bounds_check(const uint8_t* p) {
1154 return ((uint64_t)(p[0]) << 32) | ((uint64_t)(p[1]) << 24) |
1155 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 8) |
1156 ((uint64_t)(p[4]) << 0);
1157}
1158
1159static inline uint64_t //
1160wuffs_base__peek_u40le__no_bounds_check(const uint8_t* p) {
1161 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1162 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1163 ((uint64_t)(p[4]) << 32);
1164}
1165
1166static inline uint64_t //
1167wuffs_base__peek_u48be__no_bounds_check(const uint8_t* p) {
1168 return ((uint64_t)(p[0]) << 40) | ((uint64_t)(p[1]) << 32) |
1169 ((uint64_t)(p[2]) << 24) | ((uint64_t)(p[3]) << 16) |
1170 ((uint64_t)(p[4]) << 8) | ((uint64_t)(p[5]) << 0);
1171}
1172
1173static inline uint64_t //
1174wuffs_base__peek_u48le__no_bounds_check(const uint8_t* p) {
1175 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1176 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1177 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40);
1178}
1179
1180static inline uint64_t //
1181wuffs_base__peek_u56be__no_bounds_check(const uint8_t* p) {
1182 return ((uint64_t)(p[0]) << 48) | ((uint64_t)(p[1]) << 40) |
1183 ((uint64_t)(p[2]) << 32) | ((uint64_t)(p[3]) << 24) |
1184 ((uint64_t)(p[4]) << 16) | ((uint64_t)(p[5]) << 8) |
1185 ((uint64_t)(p[6]) << 0);
1186}
1187
1188static inline uint64_t //
1189wuffs_base__peek_u56le__no_bounds_check(const uint8_t* p) {
1190 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1191 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1192 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
1193 ((uint64_t)(p[6]) << 48);
1194}
1195
1196static inline uint64_t //
1197wuffs_base__peek_u64be__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001198#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1199 uint64_t x;
1200 memcpy(&x, p, 8);
1201 return _byteswap_uint64(x);
1202#else
Nigel Taoe360a532021-04-05 22:47:03 +10001203 return ((uint64_t)(p[0]) << 56) | ((uint64_t)(p[1]) << 48) |
1204 ((uint64_t)(p[2]) << 40) | ((uint64_t)(p[3]) << 32) |
1205 ((uint64_t)(p[4]) << 24) | ((uint64_t)(p[5]) << 16) |
1206 ((uint64_t)(p[6]) << 8) | ((uint64_t)(p[7]) << 0);
Nigel Taoa8205c22022-07-10 16:01:15 +10001207#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001208}
1209
1210static inline uint64_t //
1211wuffs_base__peek_u64le__no_bounds_check(const uint8_t* p) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001212#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE)
1213 uint64_t x;
1214 memcpy(&x, p, 8);
1215 return x;
1216#else
Nigel Taoe360a532021-04-05 22:47:03 +10001217 return ((uint64_t)(p[0]) << 0) | ((uint64_t)(p[1]) << 8) |
1218 ((uint64_t)(p[2]) << 16) | ((uint64_t)(p[3]) << 24) |
1219 ((uint64_t)(p[4]) << 32) | ((uint64_t)(p[5]) << 40) |
1220 ((uint64_t)(p[6]) << 48) | ((uint64_t)(p[7]) << 56);
Nigel Taoa8205c22022-07-10 16:01:15 +10001221#endif
Nigel Taoe360a532021-04-05 22:47:03 +10001222}
1223
1224// --------
1225
1226#define wuffs_base__poke_u8be__no_bounds_check \
1227 wuffs_base__poke_u8__no_bounds_check
1228#define wuffs_base__poke_u8le__no_bounds_check \
1229 wuffs_base__poke_u8__no_bounds_check
1230
1231static inline void //
1232wuffs_base__poke_u8__no_bounds_check(uint8_t* p, uint8_t x) {
1233 p[0] = x;
1234}
1235
1236static inline void //
1237wuffs_base__poke_u16be__no_bounds_check(uint8_t* p, uint16_t x) {
1238 p[0] = (uint8_t)(x >> 8);
1239 p[1] = (uint8_t)(x >> 0);
1240}
1241
1242static inline void //
1243wuffs_base__poke_u16le__no_bounds_check(uint8_t* p, uint16_t x) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001244#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE) || \
1245 (defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__))
Nigel Taoe360a532021-04-05 22:47:03 +10001246 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1247 // defines "__GNUC__".
1248 memcpy(p, &x, 2);
1249#else
1250 p[0] = (uint8_t)(x >> 0);
1251 p[1] = (uint8_t)(x >> 8);
1252#endif
1253}
1254
1255static inline void //
1256wuffs_base__poke_u24be__no_bounds_check(uint8_t* p, uint32_t x) {
1257 p[0] = (uint8_t)(x >> 16);
1258 p[1] = (uint8_t)(x >> 8);
1259 p[2] = (uint8_t)(x >> 0);
1260}
1261
1262static inline void //
1263wuffs_base__poke_u24le__no_bounds_check(uint8_t* p, uint32_t x) {
1264 p[0] = (uint8_t)(x >> 0);
1265 p[1] = (uint8_t)(x >> 8);
1266 p[2] = (uint8_t)(x >> 16);
1267}
1268
1269static inline void //
1270wuffs_base__poke_u32be__no_bounds_check(uint8_t* p, uint32_t x) {
1271 p[0] = (uint8_t)(x >> 24);
1272 p[1] = (uint8_t)(x >> 16);
1273 p[2] = (uint8_t)(x >> 8);
1274 p[3] = (uint8_t)(x >> 0);
1275}
1276
1277static inline void //
1278wuffs_base__poke_u32le__no_bounds_check(uint8_t* p, uint32_t x) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001279#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE) || \
1280 (defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__))
Nigel Taoe360a532021-04-05 22:47:03 +10001281 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1282 // defines "__GNUC__".
1283 memcpy(p, &x, 4);
1284#else
1285 p[0] = (uint8_t)(x >> 0);
1286 p[1] = (uint8_t)(x >> 8);
1287 p[2] = (uint8_t)(x >> 16);
1288 p[3] = (uint8_t)(x >> 24);
1289#endif
1290}
1291
1292static inline void //
1293wuffs_base__poke_u40be__no_bounds_check(uint8_t* p, uint64_t x) {
1294 p[0] = (uint8_t)(x >> 32);
1295 p[1] = (uint8_t)(x >> 24);
1296 p[2] = (uint8_t)(x >> 16);
1297 p[3] = (uint8_t)(x >> 8);
1298 p[4] = (uint8_t)(x >> 0);
1299}
1300
1301static inline void //
1302wuffs_base__poke_u40le__no_bounds_check(uint8_t* p, uint64_t x) {
1303 p[0] = (uint8_t)(x >> 0);
1304 p[1] = (uint8_t)(x >> 8);
1305 p[2] = (uint8_t)(x >> 16);
1306 p[3] = (uint8_t)(x >> 24);
1307 p[4] = (uint8_t)(x >> 32);
1308}
1309
1310static inline void //
1311wuffs_base__poke_u48be__no_bounds_check(uint8_t* p, uint64_t x) {
1312 p[0] = (uint8_t)(x >> 40);
1313 p[1] = (uint8_t)(x >> 32);
1314 p[2] = (uint8_t)(x >> 24);
1315 p[3] = (uint8_t)(x >> 16);
1316 p[4] = (uint8_t)(x >> 8);
1317 p[5] = (uint8_t)(x >> 0);
1318}
1319
1320static inline void //
1321wuffs_base__poke_u48le__no_bounds_check(uint8_t* p, uint64_t x) {
1322 p[0] = (uint8_t)(x >> 0);
1323 p[1] = (uint8_t)(x >> 8);
1324 p[2] = (uint8_t)(x >> 16);
1325 p[3] = (uint8_t)(x >> 24);
1326 p[4] = (uint8_t)(x >> 32);
1327 p[5] = (uint8_t)(x >> 40);
1328}
1329
1330static inline void //
1331wuffs_base__poke_u56be__no_bounds_check(uint8_t* p, uint64_t x) {
1332 p[0] = (uint8_t)(x >> 48);
1333 p[1] = (uint8_t)(x >> 40);
1334 p[2] = (uint8_t)(x >> 32);
1335 p[3] = (uint8_t)(x >> 24);
1336 p[4] = (uint8_t)(x >> 16);
1337 p[5] = (uint8_t)(x >> 8);
1338 p[6] = (uint8_t)(x >> 0);
1339}
1340
1341static inline void //
1342wuffs_base__poke_u56le__no_bounds_check(uint8_t* p, uint64_t x) {
1343 p[0] = (uint8_t)(x >> 0);
1344 p[1] = (uint8_t)(x >> 8);
1345 p[2] = (uint8_t)(x >> 16);
1346 p[3] = (uint8_t)(x >> 24);
1347 p[4] = (uint8_t)(x >> 32);
1348 p[5] = (uint8_t)(x >> 40);
1349 p[6] = (uint8_t)(x >> 48);
1350}
1351
1352static inline void //
1353wuffs_base__poke_u64be__no_bounds_check(uint8_t* p, uint64_t x) {
1354 p[0] = (uint8_t)(x >> 56);
1355 p[1] = (uint8_t)(x >> 48);
1356 p[2] = (uint8_t)(x >> 40);
1357 p[3] = (uint8_t)(x >> 32);
1358 p[4] = (uint8_t)(x >> 24);
1359 p[5] = (uint8_t)(x >> 16);
1360 p[6] = (uint8_t)(x >> 8);
1361 p[7] = (uint8_t)(x >> 0);
1362}
1363
1364static inline void //
1365wuffs_base__poke_u64le__no_bounds_check(uint8_t* p, uint64_t x) {
Nigel Taoa8205c22022-07-10 16:01:15 +10001366#if defined(WUFFS_BASE__USE_MEMCPY_LE_PEEK_POKE) || \
1367 (defined(__GNUC__) && !defined(__clang__) && defined(__x86_64__))
Nigel Taoe360a532021-04-05 22:47:03 +10001368 // This seems to perform better on gcc 10 (but not clang 9). Clang also
1369 // defines "__GNUC__".
1370 memcpy(p, &x, 8);
1371#else
1372 p[0] = (uint8_t)(x >> 0);
1373 p[1] = (uint8_t)(x >> 8);
1374 p[2] = (uint8_t)(x >> 16);
1375 p[3] = (uint8_t)(x >> 24);
1376 p[4] = (uint8_t)(x >> 32);
1377 p[5] = (uint8_t)(x >> 40);
1378 p[6] = (uint8_t)(x >> 48);
1379 p[7] = (uint8_t)(x >> 56);
1380#endif
1381}
1382
1383// --------
1384
1385// Load and Store functions are deprecated. Use Peek and Poke instead.
1386
1387#define wuffs_base__load_u8__no_bounds_check \
1388 wuffs_base__peek_u8__no_bounds_check
1389#define wuffs_base__load_u16be__no_bounds_check \
1390 wuffs_base__peek_u16be__no_bounds_check
1391#define wuffs_base__load_u16le__no_bounds_check \
1392 wuffs_base__peek_u16le__no_bounds_check
1393#define wuffs_base__load_u24be__no_bounds_check \
1394 wuffs_base__peek_u24be__no_bounds_check
1395#define wuffs_base__load_u24le__no_bounds_check \
1396 wuffs_base__peek_u24le__no_bounds_check
1397#define wuffs_base__load_u32be__no_bounds_check \
1398 wuffs_base__peek_u32be__no_bounds_check
1399#define wuffs_base__load_u32le__no_bounds_check \
1400 wuffs_base__peek_u32le__no_bounds_check
1401#define wuffs_base__load_u40be__no_bounds_check \
1402 wuffs_base__peek_u40be__no_bounds_check
1403#define wuffs_base__load_u40le__no_bounds_check \
1404 wuffs_base__peek_u40le__no_bounds_check
1405#define wuffs_base__load_u48be__no_bounds_check \
1406 wuffs_base__peek_u48be__no_bounds_check
1407#define wuffs_base__load_u48le__no_bounds_check \
1408 wuffs_base__peek_u48le__no_bounds_check
1409#define wuffs_base__load_u56be__no_bounds_check \
1410 wuffs_base__peek_u56be__no_bounds_check
1411#define wuffs_base__load_u56le__no_bounds_check \
1412 wuffs_base__peek_u56le__no_bounds_check
1413#define wuffs_base__load_u64be__no_bounds_check \
1414 wuffs_base__peek_u64be__no_bounds_check
1415#define wuffs_base__load_u64le__no_bounds_check \
1416 wuffs_base__peek_u64le__no_bounds_check
1417
1418#define wuffs_base__store_u8__no_bounds_check \
1419 wuffs_base__poke_u8__no_bounds_check
1420#define wuffs_base__store_u16be__no_bounds_check \
1421 wuffs_base__poke_u16be__no_bounds_check
1422#define wuffs_base__store_u16le__no_bounds_check \
1423 wuffs_base__poke_u16le__no_bounds_check
1424#define wuffs_base__store_u24be__no_bounds_check \
1425 wuffs_base__poke_u24be__no_bounds_check
1426#define wuffs_base__store_u24le__no_bounds_check \
1427 wuffs_base__poke_u24le__no_bounds_check
1428#define wuffs_base__store_u32be__no_bounds_check \
1429 wuffs_base__poke_u32be__no_bounds_check
1430#define wuffs_base__store_u32le__no_bounds_check \
1431 wuffs_base__poke_u32le__no_bounds_check
1432#define wuffs_base__store_u40be__no_bounds_check \
1433 wuffs_base__poke_u40be__no_bounds_check
1434#define wuffs_base__store_u40le__no_bounds_check \
1435 wuffs_base__poke_u40le__no_bounds_check
1436#define wuffs_base__store_u48be__no_bounds_check \
1437 wuffs_base__poke_u48be__no_bounds_check
1438#define wuffs_base__store_u48le__no_bounds_check \
1439 wuffs_base__poke_u48le__no_bounds_check
1440#define wuffs_base__store_u56be__no_bounds_check \
1441 wuffs_base__poke_u56be__no_bounds_check
1442#define wuffs_base__store_u56le__no_bounds_check \
1443 wuffs_base__poke_u56le__no_bounds_check
1444#define wuffs_base__store_u64be__no_bounds_check \
1445 wuffs_base__poke_u64be__no_bounds_check
1446#define wuffs_base__store_u64le__no_bounds_check \
1447 wuffs_base__poke_u64le__no_bounds_check
1448
1449// ---------------- Slices and Tables
1450
1451// WUFFS_BASE__SLICE is a 1-dimensional buffer.
1452//
1453// len measures a number of elements, not necessarily a size in bytes.
1454//
1455// A value with all fields NULL or zero is a valid, empty slice.
1456#define WUFFS_BASE__SLICE(T) \
1457 struct { \
1458 T* ptr; \
1459 size_t len; \
1460 }
1461
1462// WUFFS_BASE__TABLE is a 2-dimensional buffer.
1463//
1464// width, height and stride measure a number of elements, not necessarily a
1465// size in bytes.
1466//
1467// A value with all fields NULL or zero is a valid, empty table.
1468#define WUFFS_BASE__TABLE(T) \
1469 struct { \
1470 T* ptr; \
1471 size_t width; \
1472 size_t height; \
1473 size_t stride; \
1474 }
1475
1476typedef WUFFS_BASE__SLICE(uint8_t) wuffs_base__slice_u8;
1477typedef WUFFS_BASE__SLICE(uint16_t) wuffs_base__slice_u16;
1478typedef WUFFS_BASE__SLICE(uint32_t) wuffs_base__slice_u32;
1479typedef WUFFS_BASE__SLICE(uint64_t) wuffs_base__slice_u64;
1480
1481typedef WUFFS_BASE__TABLE(uint8_t) wuffs_base__table_u8;
1482typedef WUFFS_BASE__TABLE(uint16_t) wuffs_base__table_u16;
1483typedef WUFFS_BASE__TABLE(uint32_t) wuffs_base__table_u32;
1484typedef WUFFS_BASE__TABLE(uint64_t) wuffs_base__table_u64;
1485
1486static inline wuffs_base__slice_u8 //
1487wuffs_base__make_slice_u8(uint8_t* ptr, size_t len) {
1488 wuffs_base__slice_u8 ret;
1489 ret.ptr = ptr;
1490 ret.len = len;
1491 return ret;
1492}
1493
1494static inline wuffs_base__slice_u16 //
1495wuffs_base__make_slice_u16(uint16_t* ptr, size_t len) {
1496 wuffs_base__slice_u16 ret;
1497 ret.ptr = ptr;
1498 ret.len = len;
1499 return ret;
1500}
1501
1502static inline wuffs_base__slice_u32 //
1503wuffs_base__make_slice_u32(uint32_t* ptr, size_t len) {
1504 wuffs_base__slice_u32 ret;
1505 ret.ptr = ptr;
1506 ret.len = len;
1507 return ret;
1508}
1509
1510static inline wuffs_base__slice_u64 //
1511wuffs_base__make_slice_u64(uint64_t* ptr, size_t len) {
1512 wuffs_base__slice_u64 ret;
1513 ret.ptr = ptr;
1514 ret.len = len;
1515 return ret;
1516}
1517
1518static inline wuffs_base__slice_u8 //
Nigel Tao123a5c62022-06-03 14:17:20 +10001519wuffs_base__make_slice_u8_ij(uint8_t* ptr, size_t i, size_t j) {
1520 wuffs_base__slice_u8 ret;
1521 ret.ptr = ptr + i;
1522 ret.len = (j >= i) ? (j - i) : 0;
1523 return ret;
1524}
1525
1526static inline wuffs_base__slice_u16 //
1527wuffs_base__make_slice_u16_ij(uint16_t* ptr, size_t i, size_t j) {
1528 wuffs_base__slice_u16 ret;
1529 ret.ptr = ptr + i;
1530 ret.len = (j >= i) ? (j - i) : 0;
1531 return ret;
1532}
1533
1534static inline wuffs_base__slice_u32 //
1535wuffs_base__make_slice_u32_ij(uint32_t* ptr, size_t i, size_t j) {
1536 wuffs_base__slice_u32 ret;
1537 ret.ptr = ptr + i;
1538 ret.len = (j >= i) ? (j - i) : 0;
1539 return ret;
1540}
1541
1542static inline wuffs_base__slice_u64 //
1543wuffs_base__make_slice_u64_ij(uint64_t* ptr, size_t i, size_t j) {
1544 wuffs_base__slice_u64 ret;
1545 ret.ptr = ptr + i;
1546 ret.len = (j >= i) ? (j - i) : 0;
1547 return ret;
1548}
1549
1550static inline wuffs_base__slice_u8 //
Nigel Taoe360a532021-04-05 22:47:03 +10001551wuffs_base__empty_slice_u8() {
1552 wuffs_base__slice_u8 ret;
1553 ret.ptr = NULL;
1554 ret.len = 0;
1555 return ret;
1556}
1557
1558static inline wuffs_base__slice_u16 //
1559wuffs_base__empty_slice_u16() {
1560 wuffs_base__slice_u16 ret;
1561 ret.ptr = NULL;
1562 ret.len = 0;
1563 return ret;
1564}
1565
1566static inline wuffs_base__slice_u32 //
1567wuffs_base__empty_slice_u32() {
1568 wuffs_base__slice_u32 ret;
1569 ret.ptr = NULL;
1570 ret.len = 0;
1571 return ret;
1572}
1573
1574static inline wuffs_base__slice_u64 //
1575wuffs_base__empty_slice_u64() {
1576 wuffs_base__slice_u64 ret;
1577 ret.ptr = NULL;
1578 ret.len = 0;
1579 return ret;
1580}
1581
1582static inline wuffs_base__table_u8 //
1583wuffs_base__make_table_u8(uint8_t* ptr,
1584 size_t width,
1585 size_t height,
1586 size_t stride) {
1587 wuffs_base__table_u8 ret;
1588 ret.ptr = ptr;
1589 ret.width = width;
1590 ret.height = height;
1591 ret.stride = stride;
1592 return ret;
1593}
1594
1595static inline wuffs_base__table_u16 //
1596wuffs_base__make_table_u16(uint16_t* ptr,
1597 size_t width,
1598 size_t height,
1599 size_t stride) {
1600 wuffs_base__table_u16 ret;
1601 ret.ptr = ptr;
1602 ret.width = width;
1603 ret.height = height;
1604 ret.stride = stride;
1605 return ret;
1606}
1607
1608static inline wuffs_base__table_u32 //
1609wuffs_base__make_table_u32(uint32_t* ptr,
1610 size_t width,
1611 size_t height,
1612 size_t stride) {
1613 wuffs_base__table_u32 ret;
1614 ret.ptr = ptr;
1615 ret.width = width;
1616 ret.height = height;
1617 ret.stride = stride;
1618 return ret;
1619}
1620
1621static inline wuffs_base__table_u64 //
1622wuffs_base__make_table_u64(uint64_t* ptr,
1623 size_t width,
1624 size_t height,
1625 size_t stride) {
1626 wuffs_base__table_u64 ret;
1627 ret.ptr = ptr;
1628 ret.width = width;
1629 ret.height = height;
1630 ret.stride = stride;
1631 return ret;
1632}
1633
1634static inline wuffs_base__table_u8 //
1635wuffs_base__empty_table_u8() {
1636 wuffs_base__table_u8 ret;
1637 ret.ptr = NULL;
1638 ret.width = 0;
1639 ret.height = 0;
1640 ret.stride = 0;
1641 return ret;
1642}
1643
1644static inline wuffs_base__table_u16 //
1645wuffs_base__empty_table_u16() {
1646 wuffs_base__table_u16 ret;
1647 ret.ptr = NULL;
1648 ret.width = 0;
1649 ret.height = 0;
1650 ret.stride = 0;
1651 return ret;
1652}
1653
1654static inline wuffs_base__table_u32 //
1655wuffs_base__empty_table_u32() {
1656 wuffs_base__table_u32 ret;
1657 ret.ptr = NULL;
1658 ret.width = 0;
1659 ret.height = 0;
1660 ret.stride = 0;
1661 return ret;
1662}
1663
1664static inline wuffs_base__table_u64 //
1665wuffs_base__empty_table_u64() {
1666 wuffs_base__table_u64 ret;
1667 ret.ptr = NULL;
1668 ret.width = 0;
1669 ret.height = 0;
1670 ret.stride = 0;
1671 return ret;
1672}
1673
1674static inline bool //
1675wuffs_base__slice_u8__overlaps(wuffs_base__slice_u8 s, wuffs_base__slice_u8 t) {
1676 return ((s.ptr <= t.ptr) && (t.ptr < (s.ptr + s.len))) ||
1677 ((t.ptr <= s.ptr) && (s.ptr < (t.ptr + t.len)));
1678}
1679
1680// wuffs_base__slice_u8__subslice_i returns s[i:].
1681//
1682// It returns an empty slice if i is out of bounds.
1683static inline wuffs_base__slice_u8 //
1684wuffs_base__slice_u8__subslice_i(wuffs_base__slice_u8 s, uint64_t i) {
1685 if ((i <= SIZE_MAX) && (i <= s.len)) {
1686 return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(s.len - i)));
1687 }
1688 return wuffs_base__make_slice_u8(NULL, 0);
1689}
1690
1691// wuffs_base__slice_u8__subslice_j returns s[:j].
1692//
1693// It returns an empty slice if j is out of bounds.
1694static inline wuffs_base__slice_u8 //
1695wuffs_base__slice_u8__subslice_j(wuffs_base__slice_u8 s, uint64_t j) {
1696 if ((j <= SIZE_MAX) && (j <= s.len)) {
1697 return wuffs_base__make_slice_u8(s.ptr, ((size_t)j));
1698 }
1699 return wuffs_base__make_slice_u8(NULL, 0);
1700}
1701
1702// wuffs_base__slice_u8__subslice_ij returns s[i:j].
1703//
1704// It returns an empty slice if i or j is out of bounds.
1705static inline wuffs_base__slice_u8 //
1706wuffs_base__slice_u8__subslice_ij(wuffs_base__slice_u8 s,
1707 uint64_t i,
1708 uint64_t j) {
1709 if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) {
1710 return wuffs_base__make_slice_u8(s.ptr + i, ((size_t)(j - i)));
1711 }
1712 return wuffs_base__make_slice_u8(NULL, 0);
1713}
1714
Nigel Taobf9dab32021-11-18 19:19:55 +11001715// wuffs_base__table_u8__subtable_ij returns t[ix:jx, iy:jy].
1716//
1717// It returns an empty table if i or j is out of bounds.
1718static inline wuffs_base__table_u8 //
1719wuffs_base__table_u8__subtable_ij(wuffs_base__table_u8 t,
1720 uint64_t ix,
1721 uint64_t iy,
1722 uint64_t jx,
1723 uint64_t jy) {
1724 if ((ix <= jx) && (jx <= SIZE_MAX) && (jx <= t.width) && //
1725 (iy <= jy) && (jy <= SIZE_MAX) && (jy <= t.height)) {
1726 return wuffs_base__make_table_u8(t.ptr + ix + (iy * t.stride), //
1727 ((size_t)(jx - ix)), //
1728 ((size_t)(jy - iy)), //
1729 t.stride); //
1730 }
1731 return wuffs_base__make_table_u8(NULL, 0, 0, 0);
1732}
1733
Nigel Taoe360a532021-04-05 22:47:03 +10001734// wuffs_base__table__flattened_length returns the number of elements covered
1735// by the 1-dimensional span that backs a 2-dimensional table. This counts the
1736// elements inside the table and, when width != stride, the elements outside
1737// the table but between its rows.
1738//
1739// For example, consider a width 10, height 4, stride 10 table. Mark its first
1740// and last (inclusive) elements with 'a' and 'z'. This function returns 40.
1741//
1742// a123456789
1743// 0123456789
1744// 0123456789
1745// 012345678z
1746//
1747// Now consider the sub-table of that from (2, 1) inclusive to (8, 4) exclusive.
1748//
1749// a123456789
1750// 01iiiiiioo
1751// ooiiiiiioo
1752// ooiiiiii8z
1753//
1754// This function (called with width 6, height 3, stride 10) returns 26: 18 'i'
1755// inside elements plus 8 'o' outside elements. Note that 26 is less than a
1756// naive (height * stride = 30) computation. Indeed, advancing 29 elements from
1757// the first 'i' would venture past 'z', out of bounds of the original table.
1758//
1759// It does not check for overflow, but if the arguments come from a table that
1760// exists in memory and each element occupies a positive number of bytes then
1761// the result should be bounded by the amount of allocatable memory (which
1762// shouldn't overflow SIZE_MAX).
1763static inline size_t //
1764wuffs_base__table__flattened_length(size_t width,
1765 size_t height,
1766 size_t stride) {
1767 if (height == 0) {
1768 return 0;
1769 }
1770 return ((height - 1) * stride) + width;
1771}
1772
1773// ---------------- Magic Numbers
1774
1775// wuffs_base__magic_number_guess_fourcc guesses the file format of some data,
Nigel Taocc74cb42022-01-19 11:06:15 +11001776// given its starting bytes (the prefix_data argument) and whether or not there
1777// may be further bytes (the prefix_closed argument; true means that
1778// prefix_data is the entire data).
1779//
1780// It returns a positive FourCC value on success.
Nigel Taoe360a532021-04-05 22:47:03 +10001781//
1782// It returns zero if nothing matches its hard-coded list of 'magic numbers'.
1783//
Nigel Taocc74cb42022-01-19 11:06:15 +11001784// It returns a negative value if prefix_closed is false and a longer prefix is
1785// required for a conclusive result. For example, a single 'B' byte (without
1786// further data) is not enough to discriminate the BMP and BPG image file
1787// formats. Similarly, a single '\xFF' byte might be the start of JPEG data or
1788// it might be the start of some other binary data.
Nigel Taoe360a532021-04-05 22:47:03 +10001789//
1790// It does not do a full validity check. Like any guess made from a short
1791// prefix of the data, it may return false positives. Data that starts with 99
1792// bytes of valid JPEG followed by corruption or truncation is an invalid JPEG
1793// image overall, but this function will still return WUFFS_BASE__FOURCC__JPEG.
1794//
1795// Another source of false positives is that some 'magic numbers' are valid
1796// ASCII data. A file starting with "GIF87a and GIF89a are the two versions of
1797// GIF" will match GIF's 'magic number' even if it's plain text, not an image.
1798//
1799// For modular builds that divide the base module into sub-modules, using this
1800// function requires the WUFFS_CONFIG__MODULE__BASE__MAGIC sub-module, not just
1801// WUFFS_CONFIG__MODULE__BASE__CORE.
1802WUFFS_BASE__MAYBE_STATIC int32_t //
Nigel Taocc74cb42022-01-19 11:06:15 +11001803wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix_data,
1804 bool prefix_closed);
Nigel Taoe360a532021-04-05 22:47:03 +10001805
1806// ---------------- Ranges and Rects
1807
1808// See https://github.com/google/wuffs/blob/main/doc/note/ranges-and-rects.md
1809
1810typedef struct wuffs_base__range_ii_u32__struct {
1811 uint32_t min_incl;
1812 uint32_t max_incl;
1813
1814#ifdef __cplusplus
1815 inline bool is_empty() const;
1816 inline bool equals(wuffs_base__range_ii_u32__struct s) const;
1817 inline wuffs_base__range_ii_u32__struct intersect(
1818 wuffs_base__range_ii_u32__struct s) const;
1819 inline wuffs_base__range_ii_u32__struct unite(
1820 wuffs_base__range_ii_u32__struct s) const;
1821 inline bool contains(uint32_t x) const;
1822 inline bool contains_range(wuffs_base__range_ii_u32__struct s) const;
1823#endif // __cplusplus
1824
1825} wuffs_base__range_ii_u32;
1826
1827static inline wuffs_base__range_ii_u32 //
1828wuffs_base__empty_range_ii_u32() {
1829 wuffs_base__range_ii_u32 ret;
1830 ret.min_incl = 0;
1831 ret.max_incl = 0;
1832 return ret;
1833}
1834
1835static inline wuffs_base__range_ii_u32 //
1836wuffs_base__make_range_ii_u32(uint32_t min_incl, uint32_t max_incl) {
1837 wuffs_base__range_ii_u32 ret;
1838 ret.min_incl = min_incl;
1839 ret.max_incl = max_incl;
1840 return ret;
1841}
1842
1843static inline bool //
1844wuffs_base__range_ii_u32__is_empty(const wuffs_base__range_ii_u32* r) {
1845 return r->min_incl > r->max_incl;
1846}
1847
1848static inline bool //
1849wuffs_base__range_ii_u32__equals(const wuffs_base__range_ii_u32* r,
1850 wuffs_base__range_ii_u32 s) {
1851 return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
1852 (wuffs_base__range_ii_u32__is_empty(r) &&
1853 wuffs_base__range_ii_u32__is_empty(&s));
1854}
1855
1856static inline wuffs_base__range_ii_u32 //
1857wuffs_base__range_ii_u32__intersect(const wuffs_base__range_ii_u32* r,
1858 wuffs_base__range_ii_u32 s) {
1859 wuffs_base__range_ii_u32 t;
1860 t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
1861 t.max_incl = wuffs_base__u32__min(r->max_incl, s.max_incl);
1862 return t;
1863}
1864
1865static inline wuffs_base__range_ii_u32 //
1866wuffs_base__range_ii_u32__unite(const wuffs_base__range_ii_u32* r,
1867 wuffs_base__range_ii_u32 s) {
1868 if (wuffs_base__range_ii_u32__is_empty(r)) {
1869 return s;
1870 }
1871 if (wuffs_base__range_ii_u32__is_empty(&s)) {
1872 return *r;
1873 }
1874 wuffs_base__range_ii_u32 t;
1875 t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
1876 t.max_incl = wuffs_base__u32__max(r->max_incl, s.max_incl);
1877 return t;
1878}
1879
1880static inline bool //
1881wuffs_base__range_ii_u32__contains(const wuffs_base__range_ii_u32* r,
1882 uint32_t x) {
1883 return (r->min_incl <= x) && (x <= r->max_incl);
1884}
1885
1886static inline bool //
1887wuffs_base__range_ii_u32__contains_range(const wuffs_base__range_ii_u32* r,
1888 wuffs_base__range_ii_u32 s) {
1889 return wuffs_base__range_ii_u32__equals(
1890 &s, wuffs_base__range_ii_u32__intersect(r, s));
1891}
1892
1893#ifdef __cplusplus
1894
1895inline bool //
1896wuffs_base__range_ii_u32::is_empty() const {
1897 return wuffs_base__range_ii_u32__is_empty(this);
1898}
1899
1900inline bool //
1901wuffs_base__range_ii_u32::equals(wuffs_base__range_ii_u32 s) const {
1902 return wuffs_base__range_ii_u32__equals(this, s);
1903}
1904
1905inline wuffs_base__range_ii_u32 //
1906wuffs_base__range_ii_u32::intersect(wuffs_base__range_ii_u32 s) const {
1907 return wuffs_base__range_ii_u32__intersect(this, s);
1908}
1909
1910inline wuffs_base__range_ii_u32 //
1911wuffs_base__range_ii_u32::unite(wuffs_base__range_ii_u32 s) const {
1912 return wuffs_base__range_ii_u32__unite(this, s);
1913}
1914
1915inline bool //
1916wuffs_base__range_ii_u32::contains(uint32_t x) const {
1917 return wuffs_base__range_ii_u32__contains(this, x);
1918}
1919
1920inline bool //
1921wuffs_base__range_ii_u32::contains_range(wuffs_base__range_ii_u32 s) const {
1922 return wuffs_base__range_ii_u32__contains_range(this, s);
1923}
1924
1925#endif // __cplusplus
1926
1927// --------
1928
1929typedef struct wuffs_base__range_ie_u32__struct {
1930 uint32_t min_incl;
1931 uint32_t max_excl;
1932
1933#ifdef __cplusplus
1934 inline bool is_empty() const;
1935 inline bool equals(wuffs_base__range_ie_u32__struct s) const;
1936 inline wuffs_base__range_ie_u32__struct intersect(
1937 wuffs_base__range_ie_u32__struct s) const;
1938 inline wuffs_base__range_ie_u32__struct unite(
1939 wuffs_base__range_ie_u32__struct s) const;
1940 inline bool contains(uint32_t x) const;
1941 inline bool contains_range(wuffs_base__range_ie_u32__struct s) const;
1942 inline uint32_t length() const;
1943#endif // __cplusplus
1944
1945} wuffs_base__range_ie_u32;
1946
1947static inline wuffs_base__range_ie_u32 //
1948wuffs_base__empty_range_ie_u32() {
1949 wuffs_base__range_ie_u32 ret;
1950 ret.min_incl = 0;
1951 ret.max_excl = 0;
1952 return ret;
1953}
1954
1955static inline wuffs_base__range_ie_u32 //
1956wuffs_base__make_range_ie_u32(uint32_t min_incl, uint32_t max_excl) {
1957 wuffs_base__range_ie_u32 ret;
1958 ret.min_incl = min_incl;
1959 ret.max_excl = max_excl;
1960 return ret;
1961}
1962
1963static inline bool //
1964wuffs_base__range_ie_u32__is_empty(const wuffs_base__range_ie_u32* r) {
1965 return r->min_incl >= r->max_excl;
1966}
1967
1968static inline bool //
1969wuffs_base__range_ie_u32__equals(const wuffs_base__range_ie_u32* r,
1970 wuffs_base__range_ie_u32 s) {
1971 return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
1972 (wuffs_base__range_ie_u32__is_empty(r) &&
1973 wuffs_base__range_ie_u32__is_empty(&s));
1974}
1975
1976static inline wuffs_base__range_ie_u32 //
1977wuffs_base__range_ie_u32__intersect(const wuffs_base__range_ie_u32* r,
1978 wuffs_base__range_ie_u32 s) {
1979 wuffs_base__range_ie_u32 t;
1980 t.min_incl = wuffs_base__u32__max(r->min_incl, s.min_incl);
1981 t.max_excl = wuffs_base__u32__min(r->max_excl, s.max_excl);
1982 return t;
1983}
1984
1985static inline wuffs_base__range_ie_u32 //
1986wuffs_base__range_ie_u32__unite(const wuffs_base__range_ie_u32* r,
1987 wuffs_base__range_ie_u32 s) {
1988 if (wuffs_base__range_ie_u32__is_empty(r)) {
1989 return s;
1990 }
1991 if (wuffs_base__range_ie_u32__is_empty(&s)) {
1992 return *r;
1993 }
1994 wuffs_base__range_ie_u32 t;
1995 t.min_incl = wuffs_base__u32__min(r->min_incl, s.min_incl);
1996 t.max_excl = wuffs_base__u32__max(r->max_excl, s.max_excl);
1997 return t;
1998}
1999
2000static inline bool //
2001wuffs_base__range_ie_u32__contains(const wuffs_base__range_ie_u32* r,
2002 uint32_t x) {
2003 return (r->min_incl <= x) && (x < r->max_excl);
2004}
2005
2006static inline bool //
2007wuffs_base__range_ie_u32__contains_range(const wuffs_base__range_ie_u32* r,
2008 wuffs_base__range_ie_u32 s) {
2009 return wuffs_base__range_ie_u32__equals(
2010 &s, wuffs_base__range_ie_u32__intersect(r, s));
2011}
2012
2013static inline uint32_t //
2014wuffs_base__range_ie_u32__length(const wuffs_base__range_ie_u32* r) {
2015 return wuffs_base__u32__sat_sub(r->max_excl, r->min_incl);
2016}
2017
2018#ifdef __cplusplus
2019
2020inline bool //
2021wuffs_base__range_ie_u32::is_empty() const {
2022 return wuffs_base__range_ie_u32__is_empty(this);
2023}
2024
2025inline bool //
2026wuffs_base__range_ie_u32::equals(wuffs_base__range_ie_u32 s) const {
2027 return wuffs_base__range_ie_u32__equals(this, s);
2028}
2029
2030inline wuffs_base__range_ie_u32 //
2031wuffs_base__range_ie_u32::intersect(wuffs_base__range_ie_u32 s) const {
2032 return wuffs_base__range_ie_u32__intersect(this, s);
2033}
2034
2035inline wuffs_base__range_ie_u32 //
2036wuffs_base__range_ie_u32::unite(wuffs_base__range_ie_u32 s) const {
2037 return wuffs_base__range_ie_u32__unite(this, s);
2038}
2039
2040inline bool //
2041wuffs_base__range_ie_u32::contains(uint32_t x) const {
2042 return wuffs_base__range_ie_u32__contains(this, x);
2043}
2044
2045inline bool //
2046wuffs_base__range_ie_u32::contains_range(wuffs_base__range_ie_u32 s) const {
2047 return wuffs_base__range_ie_u32__contains_range(this, s);
2048}
2049
2050inline uint32_t //
2051wuffs_base__range_ie_u32::length() const {
2052 return wuffs_base__range_ie_u32__length(this);
2053}
2054
2055#endif // __cplusplus
2056
2057// --------
2058
2059typedef struct wuffs_base__range_ii_u64__struct {
2060 uint64_t min_incl;
2061 uint64_t max_incl;
2062
2063#ifdef __cplusplus
2064 inline bool is_empty() const;
2065 inline bool equals(wuffs_base__range_ii_u64__struct s) const;
2066 inline wuffs_base__range_ii_u64__struct intersect(
2067 wuffs_base__range_ii_u64__struct s) const;
2068 inline wuffs_base__range_ii_u64__struct unite(
2069 wuffs_base__range_ii_u64__struct s) const;
2070 inline bool contains(uint64_t x) const;
2071 inline bool contains_range(wuffs_base__range_ii_u64__struct s) const;
2072#endif // __cplusplus
2073
2074} wuffs_base__range_ii_u64;
2075
2076static inline wuffs_base__range_ii_u64 //
2077wuffs_base__empty_range_ii_u64() {
2078 wuffs_base__range_ii_u64 ret;
2079 ret.min_incl = 0;
2080 ret.max_incl = 0;
2081 return ret;
2082}
2083
2084static inline wuffs_base__range_ii_u64 //
2085wuffs_base__make_range_ii_u64(uint64_t min_incl, uint64_t max_incl) {
2086 wuffs_base__range_ii_u64 ret;
2087 ret.min_incl = min_incl;
2088 ret.max_incl = max_incl;
2089 return ret;
2090}
2091
2092static inline bool //
2093wuffs_base__range_ii_u64__is_empty(const wuffs_base__range_ii_u64* r) {
2094 return r->min_incl > r->max_incl;
2095}
2096
2097static inline bool //
2098wuffs_base__range_ii_u64__equals(const wuffs_base__range_ii_u64* r,
2099 wuffs_base__range_ii_u64 s) {
2100 return (r->min_incl == s.min_incl && r->max_incl == s.max_incl) ||
2101 (wuffs_base__range_ii_u64__is_empty(r) &&
2102 wuffs_base__range_ii_u64__is_empty(&s));
2103}
2104
2105static inline wuffs_base__range_ii_u64 //
2106wuffs_base__range_ii_u64__intersect(const wuffs_base__range_ii_u64* r,
2107 wuffs_base__range_ii_u64 s) {
2108 wuffs_base__range_ii_u64 t;
2109 t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
2110 t.max_incl = wuffs_base__u64__min(r->max_incl, s.max_incl);
2111 return t;
2112}
2113
2114static inline wuffs_base__range_ii_u64 //
2115wuffs_base__range_ii_u64__unite(const wuffs_base__range_ii_u64* r,
2116 wuffs_base__range_ii_u64 s) {
2117 if (wuffs_base__range_ii_u64__is_empty(r)) {
2118 return s;
2119 }
2120 if (wuffs_base__range_ii_u64__is_empty(&s)) {
2121 return *r;
2122 }
2123 wuffs_base__range_ii_u64 t;
2124 t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
2125 t.max_incl = wuffs_base__u64__max(r->max_incl, s.max_incl);
2126 return t;
2127}
2128
2129static inline bool //
2130wuffs_base__range_ii_u64__contains(const wuffs_base__range_ii_u64* r,
2131 uint64_t x) {
2132 return (r->min_incl <= x) && (x <= r->max_incl);
2133}
2134
2135static inline bool //
2136wuffs_base__range_ii_u64__contains_range(const wuffs_base__range_ii_u64* r,
2137 wuffs_base__range_ii_u64 s) {
2138 return wuffs_base__range_ii_u64__equals(
2139 &s, wuffs_base__range_ii_u64__intersect(r, s));
2140}
2141
2142#ifdef __cplusplus
2143
2144inline bool //
2145wuffs_base__range_ii_u64::is_empty() const {
2146 return wuffs_base__range_ii_u64__is_empty(this);
2147}
2148
2149inline bool //
2150wuffs_base__range_ii_u64::equals(wuffs_base__range_ii_u64 s) const {
2151 return wuffs_base__range_ii_u64__equals(this, s);
2152}
2153
2154inline wuffs_base__range_ii_u64 //
2155wuffs_base__range_ii_u64::intersect(wuffs_base__range_ii_u64 s) const {
2156 return wuffs_base__range_ii_u64__intersect(this, s);
2157}
2158
2159inline wuffs_base__range_ii_u64 //
2160wuffs_base__range_ii_u64::unite(wuffs_base__range_ii_u64 s) const {
2161 return wuffs_base__range_ii_u64__unite(this, s);
2162}
2163
2164inline bool //
2165wuffs_base__range_ii_u64::contains(uint64_t x) const {
2166 return wuffs_base__range_ii_u64__contains(this, x);
2167}
2168
2169inline bool //
2170wuffs_base__range_ii_u64::contains_range(wuffs_base__range_ii_u64 s) const {
2171 return wuffs_base__range_ii_u64__contains_range(this, s);
2172}
2173
2174#endif // __cplusplus
2175
2176// --------
2177
2178typedef struct wuffs_base__range_ie_u64__struct {
2179 uint64_t min_incl;
2180 uint64_t max_excl;
2181
2182#ifdef __cplusplus
2183 inline bool is_empty() const;
2184 inline bool equals(wuffs_base__range_ie_u64__struct s) const;
2185 inline wuffs_base__range_ie_u64__struct intersect(
2186 wuffs_base__range_ie_u64__struct s) const;
2187 inline wuffs_base__range_ie_u64__struct unite(
2188 wuffs_base__range_ie_u64__struct s) const;
2189 inline bool contains(uint64_t x) const;
2190 inline bool contains_range(wuffs_base__range_ie_u64__struct s) const;
2191 inline uint64_t length() const;
2192#endif // __cplusplus
2193
2194} wuffs_base__range_ie_u64;
2195
2196static inline wuffs_base__range_ie_u64 //
2197wuffs_base__empty_range_ie_u64() {
2198 wuffs_base__range_ie_u64 ret;
2199 ret.min_incl = 0;
2200 ret.max_excl = 0;
2201 return ret;
2202}
2203
2204static inline wuffs_base__range_ie_u64 //
2205wuffs_base__make_range_ie_u64(uint64_t min_incl, uint64_t max_excl) {
2206 wuffs_base__range_ie_u64 ret;
2207 ret.min_incl = min_incl;
2208 ret.max_excl = max_excl;
2209 return ret;
2210}
2211
2212static inline bool //
2213wuffs_base__range_ie_u64__is_empty(const wuffs_base__range_ie_u64* r) {
2214 return r->min_incl >= r->max_excl;
2215}
2216
2217static inline bool //
2218wuffs_base__range_ie_u64__equals(const wuffs_base__range_ie_u64* r,
2219 wuffs_base__range_ie_u64 s) {
2220 return (r->min_incl == s.min_incl && r->max_excl == s.max_excl) ||
2221 (wuffs_base__range_ie_u64__is_empty(r) &&
2222 wuffs_base__range_ie_u64__is_empty(&s));
2223}
2224
2225static inline wuffs_base__range_ie_u64 //
2226wuffs_base__range_ie_u64__intersect(const wuffs_base__range_ie_u64* r,
2227 wuffs_base__range_ie_u64 s) {
2228 wuffs_base__range_ie_u64 t;
2229 t.min_incl = wuffs_base__u64__max(r->min_incl, s.min_incl);
2230 t.max_excl = wuffs_base__u64__min(r->max_excl, s.max_excl);
2231 return t;
2232}
2233
2234static inline wuffs_base__range_ie_u64 //
2235wuffs_base__range_ie_u64__unite(const wuffs_base__range_ie_u64* r,
2236 wuffs_base__range_ie_u64 s) {
2237 if (wuffs_base__range_ie_u64__is_empty(r)) {
2238 return s;
2239 }
2240 if (wuffs_base__range_ie_u64__is_empty(&s)) {
2241 return *r;
2242 }
2243 wuffs_base__range_ie_u64 t;
2244 t.min_incl = wuffs_base__u64__min(r->min_incl, s.min_incl);
2245 t.max_excl = wuffs_base__u64__max(r->max_excl, s.max_excl);
2246 return t;
2247}
2248
2249static inline bool //
2250wuffs_base__range_ie_u64__contains(const wuffs_base__range_ie_u64* r,
2251 uint64_t x) {
2252 return (r->min_incl <= x) && (x < r->max_excl);
2253}
2254
2255static inline bool //
2256wuffs_base__range_ie_u64__contains_range(const wuffs_base__range_ie_u64* r,
2257 wuffs_base__range_ie_u64 s) {
2258 return wuffs_base__range_ie_u64__equals(
2259 &s, wuffs_base__range_ie_u64__intersect(r, s));
2260}
2261
2262static inline uint64_t //
2263wuffs_base__range_ie_u64__length(const wuffs_base__range_ie_u64* r) {
2264 return wuffs_base__u64__sat_sub(r->max_excl, r->min_incl);
2265}
2266
2267#ifdef __cplusplus
2268
2269inline bool //
2270wuffs_base__range_ie_u64::is_empty() const {
2271 return wuffs_base__range_ie_u64__is_empty(this);
2272}
2273
2274inline bool //
2275wuffs_base__range_ie_u64::equals(wuffs_base__range_ie_u64 s) const {
2276 return wuffs_base__range_ie_u64__equals(this, s);
2277}
2278
2279inline wuffs_base__range_ie_u64 //
2280wuffs_base__range_ie_u64::intersect(wuffs_base__range_ie_u64 s) const {
2281 return wuffs_base__range_ie_u64__intersect(this, s);
2282}
2283
2284inline wuffs_base__range_ie_u64 //
2285wuffs_base__range_ie_u64::unite(wuffs_base__range_ie_u64 s) const {
2286 return wuffs_base__range_ie_u64__unite(this, s);
2287}
2288
2289inline bool //
2290wuffs_base__range_ie_u64::contains(uint64_t x) const {
2291 return wuffs_base__range_ie_u64__contains(this, x);
2292}
2293
2294inline bool //
2295wuffs_base__range_ie_u64::contains_range(wuffs_base__range_ie_u64 s) const {
2296 return wuffs_base__range_ie_u64__contains_range(this, s);
2297}
2298
2299inline uint64_t //
2300wuffs_base__range_ie_u64::length() const {
2301 return wuffs_base__range_ie_u64__length(this);
2302}
2303
2304#endif // __cplusplus
2305
2306// --------
2307
2308typedef struct wuffs_base__rect_ii_u32__struct {
2309 uint32_t min_incl_x;
2310 uint32_t min_incl_y;
2311 uint32_t max_incl_x;
2312 uint32_t max_incl_y;
2313
2314#ifdef __cplusplus
2315 inline bool is_empty() const;
2316 inline bool equals(wuffs_base__rect_ii_u32__struct s) const;
2317 inline wuffs_base__rect_ii_u32__struct intersect(
2318 wuffs_base__rect_ii_u32__struct s) const;
2319 inline wuffs_base__rect_ii_u32__struct unite(
2320 wuffs_base__rect_ii_u32__struct s) const;
2321 inline bool contains(uint32_t x, uint32_t y) const;
2322 inline bool contains_rect(wuffs_base__rect_ii_u32__struct s) const;
2323#endif // __cplusplus
2324
2325} wuffs_base__rect_ii_u32;
2326
2327static inline wuffs_base__rect_ii_u32 //
2328wuffs_base__empty_rect_ii_u32() {
2329 wuffs_base__rect_ii_u32 ret;
2330 ret.min_incl_x = 0;
2331 ret.min_incl_y = 0;
2332 ret.max_incl_x = 0;
2333 ret.max_incl_y = 0;
2334 return ret;
2335}
2336
2337static inline wuffs_base__rect_ii_u32 //
2338wuffs_base__make_rect_ii_u32(uint32_t min_incl_x,
2339 uint32_t min_incl_y,
2340 uint32_t max_incl_x,
2341 uint32_t max_incl_y) {
2342 wuffs_base__rect_ii_u32 ret;
2343 ret.min_incl_x = min_incl_x;
2344 ret.min_incl_y = min_incl_y;
2345 ret.max_incl_x = max_incl_x;
2346 ret.max_incl_y = max_incl_y;
2347 return ret;
2348}
2349
2350static inline bool //
2351wuffs_base__rect_ii_u32__is_empty(const wuffs_base__rect_ii_u32* r) {
2352 return (r->min_incl_x > r->max_incl_x) || (r->min_incl_y > r->max_incl_y);
2353}
2354
2355static inline bool //
2356wuffs_base__rect_ii_u32__equals(const wuffs_base__rect_ii_u32* r,
2357 wuffs_base__rect_ii_u32 s) {
2358 return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
2359 r->max_incl_x == s.max_incl_x && r->max_incl_y == s.max_incl_y) ||
2360 (wuffs_base__rect_ii_u32__is_empty(r) &&
2361 wuffs_base__rect_ii_u32__is_empty(&s));
2362}
2363
2364static inline wuffs_base__rect_ii_u32 //
2365wuffs_base__rect_ii_u32__intersect(const wuffs_base__rect_ii_u32* r,
2366 wuffs_base__rect_ii_u32 s) {
2367 wuffs_base__rect_ii_u32 t;
2368 t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
2369 t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
2370 t.max_incl_x = wuffs_base__u32__min(r->max_incl_x, s.max_incl_x);
2371 t.max_incl_y = wuffs_base__u32__min(r->max_incl_y, s.max_incl_y);
2372 return t;
2373}
2374
2375static inline wuffs_base__rect_ii_u32 //
2376wuffs_base__rect_ii_u32__unite(const wuffs_base__rect_ii_u32* r,
2377 wuffs_base__rect_ii_u32 s) {
2378 if (wuffs_base__rect_ii_u32__is_empty(r)) {
2379 return s;
2380 }
2381 if (wuffs_base__rect_ii_u32__is_empty(&s)) {
2382 return *r;
2383 }
2384 wuffs_base__rect_ii_u32 t;
2385 t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
2386 t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
2387 t.max_incl_x = wuffs_base__u32__max(r->max_incl_x, s.max_incl_x);
2388 t.max_incl_y = wuffs_base__u32__max(r->max_incl_y, s.max_incl_y);
2389 return t;
2390}
2391
2392static inline bool //
2393wuffs_base__rect_ii_u32__contains(const wuffs_base__rect_ii_u32* r,
2394 uint32_t x,
2395 uint32_t y) {
2396 return (r->min_incl_x <= x) && (x <= r->max_incl_x) && (r->min_incl_y <= y) &&
2397 (y <= r->max_incl_y);
2398}
2399
2400static inline bool //
2401wuffs_base__rect_ii_u32__contains_rect(const wuffs_base__rect_ii_u32* r,
2402 wuffs_base__rect_ii_u32 s) {
2403 return wuffs_base__rect_ii_u32__equals(
2404 &s, wuffs_base__rect_ii_u32__intersect(r, s));
2405}
2406
2407#ifdef __cplusplus
2408
2409inline bool //
2410wuffs_base__rect_ii_u32::is_empty() const {
2411 return wuffs_base__rect_ii_u32__is_empty(this);
2412}
2413
2414inline bool //
2415wuffs_base__rect_ii_u32::equals(wuffs_base__rect_ii_u32 s) const {
2416 return wuffs_base__rect_ii_u32__equals(this, s);
2417}
2418
2419inline wuffs_base__rect_ii_u32 //
2420wuffs_base__rect_ii_u32::intersect(wuffs_base__rect_ii_u32 s) const {
2421 return wuffs_base__rect_ii_u32__intersect(this, s);
2422}
2423
2424inline wuffs_base__rect_ii_u32 //
2425wuffs_base__rect_ii_u32::unite(wuffs_base__rect_ii_u32 s) const {
2426 return wuffs_base__rect_ii_u32__unite(this, s);
2427}
2428
2429inline bool //
2430wuffs_base__rect_ii_u32::contains(uint32_t x, uint32_t y) const {
2431 return wuffs_base__rect_ii_u32__contains(this, x, y);
2432}
2433
2434inline bool //
2435wuffs_base__rect_ii_u32::contains_rect(wuffs_base__rect_ii_u32 s) const {
2436 return wuffs_base__rect_ii_u32__contains_rect(this, s);
2437}
2438
2439#endif // __cplusplus
2440
2441// --------
2442
2443typedef struct wuffs_base__rect_ie_u32__struct {
2444 uint32_t min_incl_x;
2445 uint32_t min_incl_y;
2446 uint32_t max_excl_x;
2447 uint32_t max_excl_y;
2448
2449#ifdef __cplusplus
2450 inline bool is_empty() const;
2451 inline bool equals(wuffs_base__rect_ie_u32__struct s) const;
2452 inline wuffs_base__rect_ie_u32__struct intersect(
2453 wuffs_base__rect_ie_u32__struct s) const;
2454 inline wuffs_base__rect_ie_u32__struct unite(
2455 wuffs_base__rect_ie_u32__struct s) const;
2456 inline bool contains(uint32_t x, uint32_t y) const;
2457 inline bool contains_rect(wuffs_base__rect_ie_u32__struct s) const;
2458 inline uint32_t width() const;
2459 inline uint32_t height() const;
2460#endif // __cplusplus
2461
2462} wuffs_base__rect_ie_u32;
2463
2464static inline wuffs_base__rect_ie_u32 //
2465wuffs_base__empty_rect_ie_u32() {
2466 wuffs_base__rect_ie_u32 ret;
2467 ret.min_incl_x = 0;
2468 ret.min_incl_y = 0;
2469 ret.max_excl_x = 0;
2470 ret.max_excl_y = 0;
2471 return ret;
2472}
2473
2474static inline wuffs_base__rect_ie_u32 //
2475wuffs_base__make_rect_ie_u32(uint32_t min_incl_x,
2476 uint32_t min_incl_y,
2477 uint32_t max_excl_x,
2478 uint32_t max_excl_y) {
2479 wuffs_base__rect_ie_u32 ret;
2480 ret.min_incl_x = min_incl_x;
2481 ret.min_incl_y = min_incl_y;
2482 ret.max_excl_x = max_excl_x;
2483 ret.max_excl_y = max_excl_y;
2484 return ret;
2485}
2486
2487static inline bool //
2488wuffs_base__rect_ie_u32__is_empty(const wuffs_base__rect_ie_u32* r) {
2489 return (r->min_incl_x >= r->max_excl_x) || (r->min_incl_y >= r->max_excl_y);
2490}
2491
2492static inline bool //
2493wuffs_base__rect_ie_u32__equals(const wuffs_base__rect_ie_u32* r,
2494 wuffs_base__rect_ie_u32 s) {
2495 return (r->min_incl_x == s.min_incl_x && r->min_incl_y == s.min_incl_y &&
2496 r->max_excl_x == s.max_excl_x && r->max_excl_y == s.max_excl_y) ||
2497 (wuffs_base__rect_ie_u32__is_empty(r) &&
2498 wuffs_base__rect_ie_u32__is_empty(&s));
2499}
2500
2501static inline wuffs_base__rect_ie_u32 //
2502wuffs_base__rect_ie_u32__intersect(const wuffs_base__rect_ie_u32* r,
2503 wuffs_base__rect_ie_u32 s) {
2504 wuffs_base__rect_ie_u32 t;
2505 t.min_incl_x = wuffs_base__u32__max(r->min_incl_x, s.min_incl_x);
2506 t.min_incl_y = wuffs_base__u32__max(r->min_incl_y, s.min_incl_y);
2507 t.max_excl_x = wuffs_base__u32__min(r->max_excl_x, s.max_excl_x);
2508 t.max_excl_y = wuffs_base__u32__min(r->max_excl_y, s.max_excl_y);
2509 return t;
2510}
2511
2512static inline wuffs_base__rect_ie_u32 //
2513wuffs_base__rect_ie_u32__unite(const wuffs_base__rect_ie_u32* r,
2514 wuffs_base__rect_ie_u32 s) {
2515 if (wuffs_base__rect_ie_u32__is_empty(r)) {
2516 return s;
2517 }
2518 if (wuffs_base__rect_ie_u32__is_empty(&s)) {
2519 return *r;
2520 }
2521 wuffs_base__rect_ie_u32 t;
2522 t.min_incl_x = wuffs_base__u32__min(r->min_incl_x, s.min_incl_x);
2523 t.min_incl_y = wuffs_base__u32__min(r->min_incl_y, s.min_incl_y);
2524 t.max_excl_x = wuffs_base__u32__max(r->max_excl_x, s.max_excl_x);
2525 t.max_excl_y = wuffs_base__u32__max(r->max_excl_y, s.max_excl_y);
2526 return t;
2527}
2528
2529static inline bool //
2530wuffs_base__rect_ie_u32__contains(const wuffs_base__rect_ie_u32* r,
2531 uint32_t x,
2532 uint32_t y) {
2533 return (r->min_incl_x <= x) && (x < r->max_excl_x) && (r->min_incl_y <= y) &&
2534 (y < r->max_excl_y);
2535}
2536
2537static inline bool //
2538wuffs_base__rect_ie_u32__contains_rect(const wuffs_base__rect_ie_u32* r,
2539 wuffs_base__rect_ie_u32 s) {
2540 return wuffs_base__rect_ie_u32__equals(
2541 &s, wuffs_base__rect_ie_u32__intersect(r, s));
2542}
2543
2544static inline uint32_t //
2545wuffs_base__rect_ie_u32__width(const wuffs_base__rect_ie_u32* r) {
2546 return wuffs_base__u32__sat_sub(r->max_excl_x, r->min_incl_x);
2547}
2548
2549static inline uint32_t //
2550wuffs_base__rect_ie_u32__height(const wuffs_base__rect_ie_u32* r) {
2551 return wuffs_base__u32__sat_sub(r->max_excl_y, r->min_incl_y);
2552}
2553
2554#ifdef __cplusplus
2555
2556inline bool //
2557wuffs_base__rect_ie_u32::is_empty() const {
2558 return wuffs_base__rect_ie_u32__is_empty(this);
2559}
2560
2561inline bool //
2562wuffs_base__rect_ie_u32::equals(wuffs_base__rect_ie_u32 s) const {
2563 return wuffs_base__rect_ie_u32__equals(this, s);
2564}
2565
2566inline wuffs_base__rect_ie_u32 //
2567wuffs_base__rect_ie_u32::intersect(wuffs_base__rect_ie_u32 s) const {
2568 return wuffs_base__rect_ie_u32__intersect(this, s);
2569}
2570
2571inline wuffs_base__rect_ie_u32 //
2572wuffs_base__rect_ie_u32::unite(wuffs_base__rect_ie_u32 s) const {
2573 return wuffs_base__rect_ie_u32__unite(this, s);
2574}
2575
2576inline bool //
2577wuffs_base__rect_ie_u32::contains(uint32_t x, uint32_t y) const {
2578 return wuffs_base__rect_ie_u32__contains(this, x, y);
2579}
2580
2581inline bool //
2582wuffs_base__rect_ie_u32::contains_rect(wuffs_base__rect_ie_u32 s) const {
2583 return wuffs_base__rect_ie_u32__contains_rect(this, s);
2584}
2585
2586inline uint32_t //
2587wuffs_base__rect_ie_u32::width() const {
2588 return wuffs_base__rect_ie_u32__width(this);
2589}
2590
2591inline uint32_t //
2592wuffs_base__rect_ie_u32::height() const {
2593 return wuffs_base__rect_ie_u32__height(this);
2594}
2595
2596#endif // __cplusplus
2597
2598// ---------------- More Information
2599
2600// wuffs_base__more_information holds additional fields, typically when a Wuffs
2601// method returns a [note status](/doc/note/statuses.md).
2602//
2603// The flavor field follows the base38 namespace
2604// convention](/doc/note/base38-and-fourcc.md). The other fields' semantics
2605// depends on the flavor.
2606typedef struct wuffs_base__more_information__struct {
2607 uint32_t flavor;
2608 uint32_t w;
2609 uint64_t x;
2610 uint64_t y;
2611 uint64_t z;
2612
2613#ifdef __cplusplus
2614 inline void set(uint32_t flavor_arg,
2615 uint32_t w_arg,
2616 uint64_t x_arg,
2617 uint64_t y_arg,
2618 uint64_t z_arg);
2619 inline uint32_t io_redirect__fourcc() const;
2620 inline wuffs_base__range_ie_u64 io_redirect__range() const;
2621 inline uint64_t io_seek__position() const;
2622 inline uint32_t metadata__fourcc() const;
Nigel Taobf9dab32021-11-18 19:19:55 +11002623 // Deprecated: use metadata_raw_passthrough__range.
Nigel Taoe360a532021-04-05 22:47:03 +10002624 inline wuffs_base__range_ie_u64 metadata__range() const;
Nigel Taobf9dab32021-11-18 19:19:55 +11002625 inline wuffs_base__range_ie_u64 metadata_raw_passthrough__range() const;
2626 inline int32_t metadata_parsed__chrm(uint32_t component) const;
2627 inline uint32_t metadata_parsed__gama() const;
2628 inline uint32_t metadata_parsed__srgb() const;
Nigel Taoe360a532021-04-05 22:47:03 +10002629#endif // __cplusplus
2630
2631} wuffs_base__more_information;
2632
2633#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_REDIRECT 1
2634#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_SEEK 2
Nigel Taobf9dab32021-11-18 19:19:55 +11002635// Deprecated: use
2636// WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH.
Nigel Taoe360a532021-04-05 22:47:03 +10002637#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA 3
Nigel Taobf9dab32021-11-18 19:19:55 +11002638#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH 3
2639#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_TRANSFORM 4
2640#define WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED 5
Nigel Taoe360a532021-04-05 22:47:03 +10002641
2642static inline wuffs_base__more_information //
2643wuffs_base__empty_more_information() {
2644 wuffs_base__more_information ret;
2645 ret.flavor = 0;
2646 ret.w = 0;
2647 ret.x = 0;
2648 ret.y = 0;
2649 ret.z = 0;
2650 return ret;
2651}
2652
2653static inline void //
2654wuffs_base__more_information__set(wuffs_base__more_information* m,
2655 uint32_t flavor,
2656 uint32_t w,
2657 uint64_t x,
2658 uint64_t y,
2659 uint64_t z) {
2660 if (!m) {
2661 return;
2662 }
2663 m->flavor = flavor;
2664 m->w = w;
2665 m->x = x;
2666 m->y = y;
2667 m->z = z;
2668}
2669
2670static inline uint32_t //
2671wuffs_base__more_information__io_redirect__fourcc(
2672 const wuffs_base__more_information* m) {
2673 return m->w;
2674}
2675
2676static inline wuffs_base__range_ie_u64 //
2677wuffs_base__more_information__io_redirect__range(
2678 const wuffs_base__more_information* m) {
2679 wuffs_base__range_ie_u64 ret;
2680 ret.min_incl = m->y;
2681 ret.max_excl = m->z;
2682 return ret;
2683}
2684
2685static inline uint64_t //
2686wuffs_base__more_information__io_seek__position(
2687 const wuffs_base__more_information* m) {
2688 return m->x;
2689}
2690
2691static inline uint32_t //
2692wuffs_base__more_information__metadata__fourcc(
2693 const wuffs_base__more_information* m) {
2694 return m->w;
2695}
2696
Nigel Taobf9dab32021-11-18 19:19:55 +11002697// Deprecated: use
2698// wuffs_base__more_information__metadata_raw_passthrough__range.
Nigel Taoe360a532021-04-05 22:47:03 +10002699static inline wuffs_base__range_ie_u64 //
2700wuffs_base__more_information__metadata__range(
2701 const wuffs_base__more_information* m) {
2702 wuffs_base__range_ie_u64 ret;
2703 ret.min_incl = m->y;
2704 ret.max_excl = m->z;
2705 return ret;
2706}
2707
Nigel Taobf9dab32021-11-18 19:19:55 +11002708static inline wuffs_base__range_ie_u64 //
2709wuffs_base__more_information__metadata_raw_passthrough__range(
2710 const wuffs_base__more_information* m) {
2711 wuffs_base__range_ie_u64 ret;
2712 ret.min_incl = m->y;
2713 ret.max_excl = m->z;
2714 return ret;
2715}
2716
2717#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__WHITE_X 0
2718#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__WHITE_Y 1
2719#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__RED_X 2
2720#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__RED_Y 3
2721#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__GREEN_X 4
2722#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__GREEN_Y 5
2723#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__BLUE_X 6
2724#define WUFFS_BASE__MORE_INFORMATION__METADATA_PARSED__CHRM__BLUE_Y 7
2725
2726// wuffs_base__more_information__metadata_parsed__chrm returns chromaticity
2727// values (scaled by 100000) like the PNG "cHRM" chunk. For example, the sRGB
2728// color space corresponds to:
2729// - ETC__CHRM__WHITE_X 31270
2730// - ETC__CHRM__WHITE_Y 32900
2731// - ETC__CHRM__RED_X 64000
2732// - ETC__CHRM__RED_Y 33000
2733// - ETC__CHRM__GREEN_X 30000
2734// - ETC__CHRM__GREEN_Y 60000
2735// - ETC__CHRM__BLUE_X 15000
2736// - ETC__CHRM__BLUE_Y 6000
2737//
2738// See
2739// https://ciechanow.ski/color-spaces/#chromaticity-and-white-point-coordinates
2740static inline int32_t //
2741wuffs_base__more_information__metadata_parsed__chrm(
2742 const wuffs_base__more_information* m,
2743 uint32_t component) {
2744 // After the flavor and the w field (holding a FourCC), a
2745 // wuffs_base__more_information holds 24 bytes of data in three uint64_t
2746 // typed fields (x, y and z). We pack the eight chromaticity values (wx, wy,
2747 // rx, ..., by), basically int24_t values, into 24 bytes like this:
2748 // - LSB MSB
2749 // - x: wx wx wx wy wy wy rx rx
2750 // - y: rx ry ry ry gx gx gx gy
2751 // - z: gy gy bx bx bx by by by
2752 uint32_t u = 0;
2753 switch (component & 7) {
2754 case 0:
2755 u = ((uint32_t)(m->x >> 0));
2756 break;
2757 case 1:
2758 u = ((uint32_t)(m->x >> 24));
2759 break;
2760 case 2:
2761 u = ((uint32_t)((m->x >> 48) | (m->y << 16)));
2762 break;
2763 case 3:
2764 u = ((uint32_t)(m->y >> 8));
2765 break;
2766 case 4:
2767 u = ((uint32_t)(m->y >> 32));
2768 break;
2769 case 5:
2770 u = ((uint32_t)((m->y >> 56) | (m->z << 8)));
2771 break;
2772 case 6:
2773 u = ((uint32_t)(m->z >> 16));
2774 break;
2775 case 7:
2776 u = ((uint32_t)(m->z >> 40));
2777 break;
2778 }
2779 // The left-right shifts sign-extend from 24-bit to 32-bit integers.
2780 return ((int32_t)(u << 8)) >> 8;
2781}
2782
2783// wuffs_base__more_information__metadata_parsed__gama returns inverse gamma
2784// correction values (scaled by 100000) like the PNG "gAMA" chunk. For example,
2785// for gamma = 2.2, this returns 45455 (approximating 100000 / 2.2).
2786static inline uint32_t //
2787wuffs_base__more_information__metadata_parsed__gama(
2788 const wuffs_base__more_information* m) {
2789 return ((uint32_t)(m->x));
2790}
2791
2792#define WUFFS_BASE__SRGB_RENDERING_INTENT__PERCEPTUAL 0
2793#define WUFFS_BASE__SRGB_RENDERING_INTENT__RELATIVE_COLORIMETRIC 1
2794#define WUFFS_BASE__SRGB_RENDERING_INTENT__SATURATION 2
2795#define WUFFS_BASE__SRGB_RENDERING_INTENT__ABSOLUTE_COLORIMETRIC 3
2796
2797// wuffs_base__more_information__metadata_parsed__srgb returns the sRGB
2798// rendering intent like the PNG "sRGB" chunk.
2799static inline uint32_t //
2800wuffs_base__more_information__metadata_parsed__srgb(
2801 const wuffs_base__more_information* m) {
2802 return m->x & 3;
2803}
2804
Nigel Taoe360a532021-04-05 22:47:03 +10002805#ifdef __cplusplus
2806
2807inline void //
2808wuffs_base__more_information::set(uint32_t flavor_arg,
2809 uint32_t w_arg,
2810 uint64_t x_arg,
2811 uint64_t y_arg,
2812 uint64_t z_arg) {
2813 wuffs_base__more_information__set(this, flavor_arg, w_arg, x_arg, y_arg,
2814 z_arg);
2815}
2816
2817inline uint32_t //
2818wuffs_base__more_information::io_redirect__fourcc() const {
2819 return wuffs_base__more_information__io_redirect__fourcc(this);
2820}
2821
2822inline wuffs_base__range_ie_u64 //
2823wuffs_base__more_information::io_redirect__range() const {
2824 return wuffs_base__more_information__io_redirect__range(this);
2825}
2826
2827inline uint64_t //
2828wuffs_base__more_information::io_seek__position() const {
2829 return wuffs_base__more_information__io_seek__position(this);
2830}
2831
2832inline uint32_t //
2833wuffs_base__more_information::metadata__fourcc() const {
2834 return wuffs_base__more_information__metadata__fourcc(this);
2835}
2836
2837inline wuffs_base__range_ie_u64 //
2838wuffs_base__more_information::metadata__range() const {
2839 return wuffs_base__more_information__metadata__range(this);
2840}
2841
Nigel Taobf9dab32021-11-18 19:19:55 +11002842inline wuffs_base__range_ie_u64 //
2843wuffs_base__more_information::metadata_raw_passthrough__range() const {
2844 return wuffs_base__more_information__metadata_raw_passthrough__range(this);
2845}
2846
2847inline int32_t //
2848wuffs_base__more_information::metadata_parsed__chrm(uint32_t component) const {
2849 return wuffs_base__more_information__metadata_parsed__chrm(this, component);
2850}
2851
2852inline uint32_t //
2853wuffs_base__more_information::metadata_parsed__gama() const {
2854 return wuffs_base__more_information__metadata_parsed__gama(this);
2855}
2856
2857inline uint32_t //
2858wuffs_base__more_information::metadata_parsed__srgb() const {
2859 return wuffs_base__more_information__metadata_parsed__srgb(this);
2860}
2861
Nigel Taoe360a532021-04-05 22:47:03 +10002862#endif // __cplusplus
2863
2864// ---------------- I/O
2865//
2866// See (/doc/note/io-input-output.md).
2867
2868// wuffs_base__io_buffer_meta is the metadata for a wuffs_base__io_buffer's
2869// data.
2870typedef struct wuffs_base__io_buffer_meta__struct {
2871 size_t wi; // Write index. Invariant: wi <= len.
2872 size_t ri; // Read index. Invariant: ri <= wi.
2873 uint64_t pos; // Buffer position (relative to the start of stream).
2874 bool closed; // No further writes are expected.
2875} wuffs_base__io_buffer_meta;
2876
2877// wuffs_base__io_buffer is a 1-dimensional buffer (a pointer and length) plus
2878// additional metadata.
2879//
2880// A value with all fields zero is a valid, empty buffer.
2881typedef struct wuffs_base__io_buffer__struct {
2882 wuffs_base__slice_u8 data;
2883 wuffs_base__io_buffer_meta meta;
2884
2885#ifdef __cplusplus
2886 inline bool is_valid() const;
2887 inline void compact();
2888 inline size_t reader_length() const;
2889 inline uint8_t* reader_pointer() const;
2890 inline uint64_t reader_position() const;
2891 inline wuffs_base__slice_u8 reader_slice() const;
2892 inline size_t writer_length() const;
2893 inline uint8_t* writer_pointer() const;
2894 inline uint64_t writer_position() const;
2895 inline wuffs_base__slice_u8 writer_slice() const;
2896
2897 // Deprecated: use reader_position.
2898 inline uint64_t reader_io_position() const;
2899 // Deprecated: use writer_position.
2900 inline uint64_t writer_io_position() const;
2901#endif // __cplusplus
2902
2903} wuffs_base__io_buffer;
2904
2905static inline wuffs_base__io_buffer //
2906wuffs_base__make_io_buffer(wuffs_base__slice_u8 data,
2907 wuffs_base__io_buffer_meta meta) {
2908 wuffs_base__io_buffer ret;
2909 ret.data = data;
2910 ret.meta = meta;
2911 return ret;
2912}
2913
2914static inline wuffs_base__io_buffer_meta //
2915wuffs_base__make_io_buffer_meta(size_t wi,
2916 size_t ri,
2917 uint64_t pos,
2918 bool closed) {
2919 wuffs_base__io_buffer_meta ret;
2920 ret.wi = wi;
2921 ret.ri = ri;
2922 ret.pos = pos;
2923 ret.closed = closed;
2924 return ret;
2925}
2926
2927static inline wuffs_base__io_buffer //
2928wuffs_base__ptr_u8__reader(uint8_t* ptr, size_t len, bool closed) {
2929 wuffs_base__io_buffer ret;
2930 ret.data.ptr = ptr;
2931 ret.data.len = len;
2932 ret.meta.wi = len;
2933 ret.meta.ri = 0;
2934 ret.meta.pos = 0;
2935 ret.meta.closed = closed;
2936 return ret;
2937}
2938
2939static inline wuffs_base__io_buffer //
2940wuffs_base__ptr_u8__writer(uint8_t* ptr, size_t len) {
2941 wuffs_base__io_buffer ret;
2942 ret.data.ptr = ptr;
2943 ret.data.len = len;
2944 ret.meta.wi = 0;
2945 ret.meta.ri = 0;
2946 ret.meta.pos = 0;
2947 ret.meta.closed = false;
2948 return ret;
2949}
2950
2951static inline wuffs_base__io_buffer //
2952wuffs_base__slice_u8__reader(wuffs_base__slice_u8 s, bool closed) {
2953 wuffs_base__io_buffer ret;
2954 ret.data.ptr = s.ptr;
2955 ret.data.len = s.len;
2956 ret.meta.wi = s.len;
2957 ret.meta.ri = 0;
2958 ret.meta.pos = 0;
2959 ret.meta.closed = closed;
2960 return ret;
2961}
2962
2963static inline wuffs_base__io_buffer //
2964wuffs_base__slice_u8__writer(wuffs_base__slice_u8 s) {
2965 wuffs_base__io_buffer ret;
2966 ret.data.ptr = s.ptr;
2967 ret.data.len = s.len;
2968 ret.meta.wi = 0;
2969 ret.meta.ri = 0;
2970 ret.meta.pos = 0;
2971 ret.meta.closed = false;
2972 return ret;
2973}
2974
2975static inline wuffs_base__io_buffer //
2976wuffs_base__empty_io_buffer() {
2977 wuffs_base__io_buffer ret;
2978 ret.data.ptr = NULL;
2979 ret.data.len = 0;
2980 ret.meta.wi = 0;
2981 ret.meta.ri = 0;
2982 ret.meta.pos = 0;
2983 ret.meta.closed = false;
2984 return ret;
2985}
2986
2987static inline wuffs_base__io_buffer_meta //
2988wuffs_base__empty_io_buffer_meta() {
2989 wuffs_base__io_buffer_meta ret;
2990 ret.wi = 0;
2991 ret.ri = 0;
2992 ret.pos = 0;
2993 ret.closed = false;
2994 return ret;
2995}
2996
2997static inline bool //
2998wuffs_base__io_buffer__is_valid(const wuffs_base__io_buffer* buf) {
2999 if (buf) {
3000 if (buf->data.ptr) {
3001 return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
3002 } else {
3003 return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
3004 }
3005 }
3006 return false;
3007}
3008
3009// wuffs_base__io_buffer__compact moves any written but unread bytes to the
3010// start of the buffer.
3011static inline void //
3012wuffs_base__io_buffer__compact(wuffs_base__io_buffer* buf) {
3013 if (!buf || (buf->meta.ri == 0)) {
3014 return;
3015 }
3016 buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
3017 size_t n = buf->meta.wi - buf->meta.ri;
3018 if (n != 0) {
3019 memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri, n);
3020 }
3021 buf->meta.wi = n;
3022 buf->meta.ri = 0;
3023}
3024
3025// Deprecated. Use wuffs_base__io_buffer__reader_position.
3026static inline uint64_t //
3027wuffs_base__io_buffer__reader_io_position(const wuffs_base__io_buffer* buf) {
3028 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
3029}
3030
3031static inline size_t //
3032wuffs_base__io_buffer__reader_length(const wuffs_base__io_buffer* buf) {
3033 return buf ? buf->meta.wi - buf->meta.ri : 0;
3034}
3035
3036static inline uint8_t* //
3037wuffs_base__io_buffer__reader_pointer(const wuffs_base__io_buffer* buf) {
3038 return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
3039}
3040
3041static inline uint64_t //
3042wuffs_base__io_buffer__reader_position(const wuffs_base__io_buffer* buf) {
3043 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
3044}
3045
3046static inline wuffs_base__slice_u8 //
3047wuffs_base__io_buffer__reader_slice(const wuffs_base__io_buffer* buf) {
3048 return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.ri,
3049 buf->meta.wi - buf->meta.ri)
3050 : wuffs_base__empty_slice_u8();
3051}
3052
3053// Deprecated. Use wuffs_base__io_buffer__writer_position.
3054static inline uint64_t //
3055wuffs_base__io_buffer__writer_io_position(const wuffs_base__io_buffer* buf) {
3056 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
3057}
3058
3059static inline size_t //
3060wuffs_base__io_buffer__writer_length(const wuffs_base__io_buffer* buf) {
3061 return buf ? buf->data.len - buf->meta.wi : 0;
3062}
3063
3064static inline uint8_t* //
3065wuffs_base__io_buffer__writer_pointer(const wuffs_base__io_buffer* buf) {
3066 return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
3067}
3068
3069static inline uint64_t //
3070wuffs_base__io_buffer__writer_position(const wuffs_base__io_buffer* buf) {
3071 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
3072}
3073
3074static inline wuffs_base__slice_u8 //
3075wuffs_base__io_buffer__writer_slice(const wuffs_base__io_buffer* buf) {
3076 return buf ? wuffs_base__make_slice_u8(buf->data.ptr + buf->meta.wi,
3077 buf->data.len - buf->meta.wi)
3078 : wuffs_base__empty_slice_u8();
3079}
3080
3081#ifdef __cplusplus
3082
3083inline bool //
3084wuffs_base__io_buffer::is_valid() const {
3085 return wuffs_base__io_buffer__is_valid(this);
3086}
3087
3088inline void //
3089wuffs_base__io_buffer::compact() {
3090 wuffs_base__io_buffer__compact(this);
3091}
3092
3093inline uint64_t //
3094wuffs_base__io_buffer::reader_io_position() const {
3095 return wuffs_base__io_buffer__reader_io_position(this);
3096}
3097
3098inline size_t //
3099wuffs_base__io_buffer::reader_length() const {
3100 return wuffs_base__io_buffer__reader_length(this);
3101}
3102
3103inline uint8_t* //
3104wuffs_base__io_buffer::reader_pointer() const {
3105 return wuffs_base__io_buffer__reader_pointer(this);
3106}
3107
3108inline uint64_t //
3109wuffs_base__io_buffer::reader_position() const {
3110 return wuffs_base__io_buffer__reader_position(this);
3111}
3112
3113inline wuffs_base__slice_u8 //
3114wuffs_base__io_buffer::reader_slice() const {
3115 return wuffs_base__io_buffer__reader_slice(this);
3116}
3117
3118inline uint64_t //
3119wuffs_base__io_buffer::writer_io_position() const {
3120 return wuffs_base__io_buffer__writer_io_position(this);
3121}
3122
3123inline size_t //
3124wuffs_base__io_buffer::writer_length() const {
3125 return wuffs_base__io_buffer__writer_length(this);
3126}
3127
3128inline uint8_t* //
3129wuffs_base__io_buffer::writer_pointer() const {
3130 return wuffs_base__io_buffer__writer_pointer(this);
3131}
3132
3133inline uint64_t //
3134wuffs_base__io_buffer::writer_position() const {
3135 return wuffs_base__io_buffer__writer_position(this);
3136}
3137
3138inline wuffs_base__slice_u8 //
3139wuffs_base__io_buffer::writer_slice() const {
3140 return wuffs_base__io_buffer__writer_slice(this);
3141}
3142
3143#endif // __cplusplus
3144
3145// ---------------- Tokens
3146
3147// wuffs_base__token is an element of a byte stream's tokenization.
3148//
3149// See https://github.com/google/wuffs/blob/main/doc/note/tokens.md
3150typedef struct wuffs_base__token__struct {
3151 uint64_t repr;
3152
3153#ifdef __cplusplus
3154 inline int64_t value() const;
3155 inline int64_t value_extension() const;
3156 inline int64_t value_major() const;
3157 inline int64_t value_base_category() const;
3158 inline uint64_t value_minor() const;
3159 inline uint64_t value_base_detail() const;
3160 inline int64_t value_base_detail__sign_extended() const;
3161 inline bool continued() const;
3162 inline uint64_t length() const;
3163#endif // __cplusplus
3164
3165} wuffs_base__token;
3166
3167static inline wuffs_base__token //
3168wuffs_base__make_token(uint64_t repr) {
3169 wuffs_base__token ret;
3170 ret.repr = repr;
3171 return ret;
3172}
3173
3174// --------
3175
3176#define WUFFS_BASE__TOKEN__LENGTH__MAX_INCL 0xFFFF
3177
3178#define WUFFS_BASE__TOKEN__VALUE__SHIFT 17
3179#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT 17
3180#define WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT 42
3181#define WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT 17
3182#define WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT 38
3183#define WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT 17
3184#define WUFFS_BASE__TOKEN__CONTINUED__SHIFT 16
3185#define WUFFS_BASE__TOKEN__LENGTH__SHIFT 0
3186
3187#define WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS 46
3188
3189// --------
3190
3191#define WUFFS_BASE__TOKEN__VBC__FILLER 0
3192#define WUFFS_BASE__TOKEN__VBC__STRUCTURE 1
3193#define WUFFS_BASE__TOKEN__VBC__STRING 2
3194#define WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT 3
3195#define WUFFS_BASE__TOKEN__VBC__LITERAL 4
3196#define WUFFS_BASE__TOKEN__VBC__NUMBER 5
3197#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED 6
3198#define WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED 7
3199
3200// --------
3201
3202#define WUFFS_BASE__TOKEN__VBD__FILLER__PUNCTUATION 0x00001
3203#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_BLOCK 0x00002
3204#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_LINE 0x00004
3205
3206// COMMENT_ANY is a bit-wise or of COMMENT_BLOCK AND COMMENT_LINE.
3207#define WUFFS_BASE__TOKEN__VBD__FILLER__COMMENT_ANY 0x00006
3208
3209// --------
3210
3211#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH 0x00001
3212#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP 0x00002
3213#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE 0x00010
3214#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST 0x00020
3215#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT 0x00040
3216#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE 0x01000
3217#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST 0x02000
3218#define WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT 0x04000
3219
3220// --------
3221
3222// DEFINITELY_FOO means that the destination bytes (and also the source bytes,
3223// for 1_DST_1_SRC_COPY) are in the FOO format. Definitely means that the lack
3224// of the bit means "maybe FOO". It does not necessarily mean "not FOO".
3225//
3226// CHAIN_ETC means that decoding the entire token chain forms a UTF-8 or ASCII
3227// string, not just this current token. CHAIN_ETC_UTF_8 therefore distinguishes
3228// Unicode (UTF-8) strings from byte strings. MUST means that the the token
3229// producer (e.g. parser) must verify this. SHOULD means that the token
3230// consumer (e.g. renderer) should verify this.
3231//
3232// When a CHAIN_ETC_UTF_8 bit is set, the parser must ensure that non-ASCII
3233// code points (with multi-byte UTF-8 encodings) do not straddle token
3234// boundaries. Checking UTF-8 validity can inspect each token separately.
3235//
3236// The lack of any particular bit is conservative: it is valid for all-ASCII
3237// strings, in a single- or multi-token chain, to have none of these bits set.
3238#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_UTF_8 0x00001
3239#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8 0x00002
3240#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_UTF_8 0x00004
3241#define WUFFS_BASE__TOKEN__VBD__STRING__DEFINITELY_ASCII 0x00010
3242#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_ASCII 0x00020
3243#define WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_SHOULD_BE_ASCII 0x00040
3244
3245// CONVERT_D_DST_S_SRC means that multiples of S source bytes (possibly padded)
3246// produces multiples of D destination bytes. For example,
3247// CONVERT_1_DST_4_SRC_BACKSLASH_X means a source like "\\x23\\x67\\xAB", where
3248// 12 src bytes encode 3 dst bytes.
3249//
3250// Post-processing may further transform those D destination bytes (e.g. treat
3251// "\\xFF" as the Unicode code point U+00FF instead of the byte 0xFF), but that
3252// is out of scope of this VBD's semantics.
3253//
3254// When src is the empty string, multiple conversion algorithms are applicable
3255// (so these bits are not necessarily mutually exclusive), all producing the
3256// same empty dst string.
3257#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP 0x00100
3258#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY 0x00200
3259#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_2_SRC_HEXADECIMAL 0x00400
3260#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_4_SRC_BACKSLASH_X 0x00800
3261#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_STD 0x01000
3262#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_3_DST_4_SRC_BASE_64_URL 0x02000
3263#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_4_DST_5_SRC_ASCII_85 0x04000
3264#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_HEX 0x08000
3265#define WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_5_DST_8_SRC_BASE_32_STD 0x10000
3266
3267// --------
3268
3269#define WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED 0x00001
3270#define WUFFS_BASE__TOKEN__VBD__LITERAL__NULL 0x00002
3271#define WUFFS_BASE__TOKEN__VBD__LITERAL__FALSE 0x00004
3272#define WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE 0x00008
3273
3274// --------
3275
3276// For a source string of "123" or "0x9A", it is valid for a tokenizer to
3277// return any combination of:
3278// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT.
3279// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED.
3280// - WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED.
3281//
3282// For a source string of "+123" or "-0x9A", only the first two are valid.
3283//
3284// For a source string of "123.", only the first one is valid.
3285#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT 0x00001
3286#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED 0x00002
3287#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_UNSIGNED 0x00004
3288
3289#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF 0x00010
3290#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF 0x00020
3291#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN 0x00040
3292#define WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN 0x00080
3293
3294// The number 300 might be represented as "\x01\x2C", "\x2C\x01\x00\x00" or
3295// "300", which are big-endian, little-endian or text. For binary formats, the
3296// token length (after adjusting for FORMAT_IGNORE_ETC) discriminates
3297// e.g. u16 little-endian vs u32 little-endian.
3298#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN 0x00100
3299#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_LITTLE_ENDIAN 0x00200
3300#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT 0x00400
3301
3302#define WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE 0x01000
3303
3304// --------
3305
3306// wuffs_base__token__value returns the token's high 46 bits, sign-extended. A
3307// negative value means an extended token, non-negative means a simple token.
3308static inline int64_t //
3309wuffs_base__token__value(const wuffs_base__token* t) {
3310 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE__SHIFT;
3311}
3312
3313// wuffs_base__token__value_extension returns a negative value if the token was
3314// not an extended token.
3315static inline int64_t //
3316wuffs_base__token__value_extension(const wuffs_base__token* t) {
3317 return (~(int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT;
3318}
3319
3320// wuffs_base__token__value_major returns a negative value if the token was not
3321// a simple token.
3322static inline int64_t //
3323wuffs_base__token__value_major(const wuffs_base__token* t) {
3324 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT;
3325}
3326
3327// wuffs_base__token__value_base_category returns a negative value if the token
3328// was not a simple token.
3329static inline int64_t //
3330wuffs_base__token__value_base_category(const wuffs_base__token* t) {
3331 return ((int64_t)(t->repr)) >> WUFFS_BASE__TOKEN__VALUE_BASE_CATEGORY__SHIFT;
3332}
3333
3334static inline uint64_t //
3335wuffs_base__token__value_minor(const wuffs_base__token* t) {
3336 return (t->repr >> WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) & 0x1FFFFFF;
3337}
3338
3339static inline uint64_t //
3340wuffs_base__token__value_base_detail(const wuffs_base__token* t) {
3341 return (t->repr >> WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT) & 0x1FFFFF;
3342}
3343
3344static inline int64_t //
3345wuffs_base__token__value_base_detail__sign_extended(
3346 const wuffs_base__token* t) {
3347 // The VBD is 21 bits in the middle of t->repr. Left shift the high (64 - 21
3348 // - ETC__SHIFT) bits off, then right shift (sign-extending) back down.
3349 uint64_t u = t->repr << (43 - WUFFS_BASE__TOKEN__VALUE_BASE_DETAIL__SHIFT);
3350 return ((int64_t)u) >> 43;
3351}
3352
3353static inline bool //
3354wuffs_base__token__continued(const wuffs_base__token* t) {
3355 return t->repr & 0x10000;
3356}
3357
3358static inline uint64_t //
3359wuffs_base__token__length(const wuffs_base__token* t) {
3360 return (t->repr >> WUFFS_BASE__TOKEN__LENGTH__SHIFT) & 0xFFFF;
3361}
3362
3363#ifdef __cplusplus
3364
3365inline int64_t //
3366wuffs_base__token::value() const {
3367 return wuffs_base__token__value(this);
3368}
3369
3370inline int64_t //
3371wuffs_base__token::value_extension() const {
3372 return wuffs_base__token__value_extension(this);
3373}
3374
3375inline int64_t //
3376wuffs_base__token::value_major() const {
3377 return wuffs_base__token__value_major(this);
3378}
3379
3380inline int64_t //
3381wuffs_base__token::value_base_category() const {
3382 return wuffs_base__token__value_base_category(this);
3383}
3384
3385inline uint64_t //
3386wuffs_base__token::value_minor() const {
3387 return wuffs_base__token__value_minor(this);
3388}
3389
3390inline uint64_t //
3391wuffs_base__token::value_base_detail() const {
3392 return wuffs_base__token__value_base_detail(this);
3393}
3394
3395inline int64_t //
3396wuffs_base__token::value_base_detail__sign_extended() const {
3397 return wuffs_base__token__value_base_detail__sign_extended(this);
3398}
3399
3400inline bool //
3401wuffs_base__token::continued() const {
3402 return wuffs_base__token__continued(this);
3403}
3404
3405inline uint64_t //
3406wuffs_base__token::length() const {
3407 return wuffs_base__token__length(this);
3408}
3409
3410#endif // __cplusplus
3411
3412// --------
3413
3414typedef WUFFS_BASE__SLICE(wuffs_base__token) wuffs_base__slice_token;
3415
3416static inline wuffs_base__slice_token //
3417wuffs_base__make_slice_token(wuffs_base__token* ptr, size_t len) {
3418 wuffs_base__slice_token ret;
3419 ret.ptr = ptr;
3420 ret.len = len;
3421 return ret;
3422}
3423
3424static inline wuffs_base__slice_token //
3425wuffs_base__empty_slice_token() {
3426 wuffs_base__slice_token ret;
3427 ret.ptr = NULL;
3428 ret.len = 0;
3429 return ret;
3430}
3431
3432// --------
3433
3434// wuffs_base__token_buffer_meta is the metadata for a
3435// wuffs_base__token_buffer's data.
3436typedef struct wuffs_base__token_buffer_meta__struct {
3437 size_t wi; // Write index. Invariant: wi <= len.
3438 size_t ri; // Read index. Invariant: ri <= wi.
3439 uint64_t pos; // Position of the buffer start relative to the stream start.
3440 bool closed; // No further writes are expected.
3441} wuffs_base__token_buffer_meta;
3442
3443// wuffs_base__token_buffer is a 1-dimensional buffer (a pointer and length)
3444// plus additional metadata.
3445//
3446// A value with all fields zero is a valid, empty buffer.
3447typedef struct wuffs_base__token_buffer__struct {
3448 wuffs_base__slice_token data;
3449 wuffs_base__token_buffer_meta meta;
3450
3451#ifdef __cplusplus
3452 inline bool is_valid() const;
3453 inline void compact();
3454 inline uint64_t reader_length() const;
3455 inline wuffs_base__token* reader_pointer() const;
3456 inline wuffs_base__slice_token reader_slice() const;
3457 inline uint64_t reader_token_position() const;
3458 inline uint64_t writer_length() const;
3459 inline uint64_t writer_token_position() const;
3460 inline wuffs_base__token* writer_pointer() const;
3461 inline wuffs_base__slice_token writer_slice() const;
3462#endif // __cplusplus
3463
3464} wuffs_base__token_buffer;
3465
3466static inline wuffs_base__token_buffer //
3467wuffs_base__make_token_buffer(wuffs_base__slice_token data,
3468 wuffs_base__token_buffer_meta meta) {
3469 wuffs_base__token_buffer ret;
3470 ret.data = data;
3471 ret.meta = meta;
3472 return ret;
3473}
3474
3475static inline wuffs_base__token_buffer_meta //
3476wuffs_base__make_token_buffer_meta(size_t wi,
3477 size_t ri,
3478 uint64_t pos,
3479 bool closed) {
3480 wuffs_base__token_buffer_meta ret;
3481 ret.wi = wi;
3482 ret.ri = ri;
3483 ret.pos = pos;
3484 ret.closed = closed;
3485 return ret;
3486}
3487
3488static inline wuffs_base__token_buffer //
3489wuffs_base__slice_token__reader(wuffs_base__slice_token s, bool closed) {
3490 wuffs_base__token_buffer ret;
3491 ret.data.ptr = s.ptr;
3492 ret.data.len = s.len;
3493 ret.meta.wi = s.len;
3494 ret.meta.ri = 0;
3495 ret.meta.pos = 0;
3496 ret.meta.closed = closed;
3497 return ret;
3498}
3499
3500static inline wuffs_base__token_buffer //
3501wuffs_base__slice_token__writer(wuffs_base__slice_token s) {
3502 wuffs_base__token_buffer ret;
3503 ret.data.ptr = s.ptr;
3504 ret.data.len = s.len;
3505 ret.meta.wi = 0;
3506 ret.meta.ri = 0;
3507 ret.meta.pos = 0;
3508 ret.meta.closed = false;
3509 return ret;
3510}
3511
3512static inline wuffs_base__token_buffer //
3513wuffs_base__empty_token_buffer() {
3514 wuffs_base__token_buffer ret;
3515 ret.data.ptr = NULL;
3516 ret.data.len = 0;
3517 ret.meta.wi = 0;
3518 ret.meta.ri = 0;
3519 ret.meta.pos = 0;
3520 ret.meta.closed = false;
3521 return ret;
3522}
3523
3524static inline wuffs_base__token_buffer_meta //
3525wuffs_base__empty_token_buffer_meta() {
3526 wuffs_base__token_buffer_meta ret;
3527 ret.wi = 0;
3528 ret.ri = 0;
3529 ret.pos = 0;
3530 ret.closed = false;
3531 return ret;
3532}
3533
3534static inline bool //
3535wuffs_base__token_buffer__is_valid(const wuffs_base__token_buffer* buf) {
3536 if (buf) {
3537 if (buf->data.ptr) {
3538 return (buf->meta.ri <= buf->meta.wi) && (buf->meta.wi <= buf->data.len);
3539 } else {
3540 return (buf->meta.ri == 0) && (buf->meta.wi == 0) && (buf->data.len == 0);
3541 }
3542 }
3543 return false;
3544}
3545
3546// wuffs_base__token_buffer__compact moves any written but unread tokens to the
3547// start of the buffer.
3548static inline void //
3549wuffs_base__token_buffer__compact(wuffs_base__token_buffer* buf) {
3550 if (!buf || (buf->meta.ri == 0)) {
3551 return;
3552 }
3553 buf->meta.pos = wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri);
3554 size_t n = buf->meta.wi - buf->meta.ri;
3555 if (n != 0) {
3556 memmove(buf->data.ptr, buf->data.ptr + buf->meta.ri,
3557 n * sizeof(wuffs_base__token));
3558 }
3559 buf->meta.wi = n;
3560 buf->meta.ri = 0;
3561}
3562
3563static inline uint64_t //
3564wuffs_base__token_buffer__reader_length(const wuffs_base__token_buffer* buf) {
3565 return buf ? buf->meta.wi - buf->meta.ri : 0;
3566}
3567
3568static inline wuffs_base__token* //
3569wuffs_base__token_buffer__reader_pointer(const wuffs_base__token_buffer* buf) {
3570 return buf ? (buf->data.ptr + buf->meta.ri) : NULL;
3571}
3572
3573static inline wuffs_base__slice_token //
3574wuffs_base__token_buffer__reader_slice(const wuffs_base__token_buffer* buf) {
3575 return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.ri,
3576 buf->meta.wi - buf->meta.ri)
3577 : wuffs_base__empty_slice_token();
3578}
3579
3580static inline uint64_t //
3581wuffs_base__token_buffer__reader_token_position(
3582 const wuffs_base__token_buffer* buf) {
3583 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.ri) : 0;
3584}
3585
3586static inline uint64_t //
3587wuffs_base__token_buffer__writer_length(const wuffs_base__token_buffer* buf) {
3588 return buf ? buf->data.len - buf->meta.wi : 0;
3589}
3590
3591static inline wuffs_base__token* //
3592wuffs_base__token_buffer__writer_pointer(const wuffs_base__token_buffer* buf) {
3593 return buf ? (buf->data.ptr + buf->meta.wi) : NULL;
3594}
3595
3596static inline wuffs_base__slice_token //
3597wuffs_base__token_buffer__writer_slice(const wuffs_base__token_buffer* buf) {
3598 return buf ? wuffs_base__make_slice_token(buf->data.ptr + buf->meta.wi,
3599 buf->data.len - buf->meta.wi)
3600 : wuffs_base__empty_slice_token();
3601}
3602
3603static inline uint64_t //
3604wuffs_base__token_buffer__writer_token_position(
3605 const wuffs_base__token_buffer* buf) {
3606 return buf ? wuffs_base__u64__sat_add(buf->meta.pos, buf->meta.wi) : 0;
3607}
3608
3609#ifdef __cplusplus
3610
3611inline bool //
3612wuffs_base__token_buffer::is_valid() const {
3613 return wuffs_base__token_buffer__is_valid(this);
3614}
3615
3616inline void //
3617wuffs_base__token_buffer::compact() {
3618 wuffs_base__token_buffer__compact(this);
3619}
3620
3621inline uint64_t //
3622wuffs_base__token_buffer::reader_length() const {
3623 return wuffs_base__token_buffer__reader_length(this);
3624}
3625
3626inline wuffs_base__token* //
3627wuffs_base__token_buffer::reader_pointer() const {
3628 return wuffs_base__token_buffer__reader_pointer(this);
3629}
3630
3631inline wuffs_base__slice_token //
3632wuffs_base__token_buffer::reader_slice() const {
3633 return wuffs_base__token_buffer__reader_slice(this);
3634}
3635
3636inline uint64_t //
3637wuffs_base__token_buffer::reader_token_position() const {
3638 return wuffs_base__token_buffer__reader_token_position(this);
3639}
3640
3641inline uint64_t //
3642wuffs_base__token_buffer::writer_length() const {
3643 return wuffs_base__token_buffer__writer_length(this);
3644}
3645
3646inline wuffs_base__token* //
3647wuffs_base__token_buffer::writer_pointer() const {
3648 return wuffs_base__token_buffer__writer_pointer(this);
3649}
3650
3651inline wuffs_base__slice_token //
3652wuffs_base__token_buffer::writer_slice() const {
3653 return wuffs_base__token_buffer__writer_slice(this);
3654}
3655
3656inline uint64_t //
3657wuffs_base__token_buffer::writer_token_position() const {
3658 return wuffs_base__token_buffer__writer_token_position(this);
3659}
3660
3661#endif // __cplusplus
3662
3663// ---------------- Memory Allocation
3664
3665// The memory allocation related functions in this section aren't used by Wuffs
3666// per se, but they may be helpful to the code that uses Wuffs.
3667
3668// wuffs_base__malloc_slice_uxx wraps calling a malloc-like function, except
3669// that it takes a uint64_t number of elements instead of a size_t size in
3670// bytes, and it returns a slice (a pointer and a length) instead of just a
3671// pointer.
3672//
3673// You can pass the C stdlib's malloc as the malloc_func.
3674//
3675// It returns an empty slice (containing a NULL ptr field) if (num_uxx *
3676// sizeof(uintxx_t)) would overflow SIZE_MAX.
3677
3678static inline wuffs_base__slice_u8 //
3679wuffs_base__malloc_slice_u8(void* (*malloc_func)(size_t), uint64_t num_u8) {
3680 if (malloc_func && (num_u8 <= (SIZE_MAX / sizeof(uint8_t)))) {
3681 void* p = (*malloc_func)((size_t)(num_u8 * sizeof(uint8_t)));
3682 if (p) {
3683 return wuffs_base__make_slice_u8((uint8_t*)(p), (size_t)num_u8);
3684 }
3685 }
3686 return wuffs_base__make_slice_u8(NULL, 0);
3687}
3688
3689static inline wuffs_base__slice_u16 //
3690wuffs_base__malloc_slice_u16(void* (*malloc_func)(size_t), uint64_t num_u16) {
3691 if (malloc_func && (num_u16 <= (SIZE_MAX / sizeof(uint16_t)))) {
3692 void* p = (*malloc_func)((size_t)(num_u16 * sizeof(uint16_t)));
3693 if (p) {
3694 return wuffs_base__make_slice_u16((uint16_t*)(p), (size_t)num_u16);
3695 }
3696 }
3697 return wuffs_base__make_slice_u16(NULL, 0);
3698}
3699
3700static inline wuffs_base__slice_u32 //
3701wuffs_base__malloc_slice_u32(void* (*malloc_func)(size_t), uint64_t num_u32) {
3702 if (malloc_func && (num_u32 <= (SIZE_MAX / sizeof(uint32_t)))) {
3703 void* p = (*malloc_func)((size_t)(num_u32 * sizeof(uint32_t)));
3704 if (p) {
3705 return wuffs_base__make_slice_u32((uint32_t*)(p), (size_t)num_u32);
3706 }
3707 }
3708 return wuffs_base__make_slice_u32(NULL, 0);
3709}
3710
3711static inline wuffs_base__slice_u64 //
3712wuffs_base__malloc_slice_u64(void* (*malloc_func)(size_t), uint64_t num_u64) {
3713 if (malloc_func && (num_u64 <= (SIZE_MAX / sizeof(uint64_t)))) {
3714 void* p = (*malloc_func)((size_t)(num_u64 * sizeof(uint64_t)));
3715 if (p) {
3716 return wuffs_base__make_slice_u64((uint64_t*)(p), (size_t)num_u64);
3717 }
3718 }
3719 return wuffs_base__make_slice_u64(NULL, 0);
3720}
3721
3722// ---------------- Images
3723
3724// wuffs_base__color_u32_argb_premul is an 8 bit per channel premultiplied
3725// Alpha, Red, Green, Blue color, as a uint32_t value. Its value is always
3726// 0xAARRGGBB (Alpha most significant, Blue least), regardless of endianness.
3727typedef uint32_t wuffs_base__color_u32_argb_premul;
3728
3729// wuffs_base__color_u32_argb_premul__is_valid returns whether c's Red, Green
3730// and Blue channels are all less than or equal to its Alpha channel. c uses
3731// premultiplied alpha, so 50% opaque 100% saturated red is 0x7F7F_0000 and a
3732// value like 0x7F80_0000 is invalid.
3733static inline bool //
3734wuffs_base__color_u32_argb_premul__is_valid(
3735 wuffs_base__color_u32_argb_premul c) {
3736 uint32_t a = 0xFF & (c >> 24);
3737 uint32_t r = 0xFF & (c >> 16);
3738 uint32_t g = 0xFF & (c >> 8);
3739 uint32_t b = 0xFF & (c >> 0);
3740 return (a >= r) && (a >= g) && (a >= b);
3741}
3742
3743static inline uint16_t //
3744wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
3745 wuffs_base__color_u32_argb_premul c) {
3746 uint32_t r5 = 0xF800 & (c >> 8);
3747 uint32_t g6 = 0x07E0 & (c >> 5);
3748 uint32_t b5 = 0x001F & (c >> 3);
3749 return (uint16_t)(r5 | g6 | b5);
3750}
3751
3752static inline wuffs_base__color_u32_argb_premul //
3753wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(uint16_t rgb_565) {
3754 uint32_t b5 = 0x1F & (rgb_565 >> 0);
3755 uint32_t b = (b5 << 3) | (b5 >> 2);
3756 uint32_t g6 = 0x3F & (rgb_565 >> 5);
3757 uint32_t g = (g6 << 2) | (g6 >> 4);
3758 uint32_t r5 = 0x1F & (rgb_565 >> 11);
3759 uint32_t r = (r5 << 3) | (r5 >> 2);
3760 return 0xFF000000 | (r << 16) | (g << 8) | (b << 0);
3761}
3762
3763static inline uint8_t //
3764wuffs_base__color_u32_argb_premul__as__color_u8_gray(
3765 wuffs_base__color_u32_argb_premul c) {
3766 // Work in 16-bit color.
3767 uint32_t cr = 0x101 * (0xFF & (c >> 16));
3768 uint32_t cg = 0x101 * (0xFF & (c >> 8));
3769 uint32_t cb = 0x101 * (0xFF & (c >> 0));
3770
3771 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
3772 // as those given by the JFIF specification.
3773 //
3774 // Note that 19595 + 38470 + 7471 equals 65536, also known as (1 << 16). We
3775 // shift by 24, not just by 16, because the return value is 8-bit color, not
3776 // 16-bit color.
3777 uint32_t weighted_average = (19595 * cr) + (38470 * cg) + (7471 * cb) + 32768;
3778 return (uint8_t)(weighted_average >> 24);
3779}
3780
3781static inline uint16_t //
3782wuffs_base__color_u32_argb_premul__as__color_u16_gray(
3783 wuffs_base__color_u32_argb_premul c) {
3784 // Work in 16-bit color.
3785 uint32_t cr = 0x101 * (0xFF & (c >> 16));
3786 uint32_t cg = 0x101 * (0xFF & (c >> 8));
3787 uint32_t cb = 0x101 * (0xFF & (c >> 0));
3788
3789 // These coefficients (the fractions 0.299, 0.587 and 0.114) are the same
3790 // as those given by the JFIF specification.
3791 //
3792 // Note that 19595 + 38470 + 7471 equals 65536, also known as (1 << 16).
3793 uint32_t weighted_average = (19595 * cr) + (38470 * cg) + (7471 * cb) + 32768;
3794 return (uint16_t)(weighted_average >> 16);
3795}
3796
3797// wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul converts
3798// from non-premultiplied alpha to premultiplied alpha.
3799static inline wuffs_base__color_u32_argb_premul //
3800wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
3801 uint32_t argb_nonpremul) {
3802 // Multiplying by 0x101 (twice, once for alpha and once for color) converts
3803 // from 8-bit to 16-bit color. Shifting right by 8 undoes that.
3804 //
3805 // Working in the higher bit depth can produce slightly different (and
3806 // arguably slightly more accurate) results. For example, given 8-bit blue
3807 // and alpha of 0x80 and 0x81:
3808 //
3809 // - ((0x80 * 0x81 ) / 0xFF ) = 0x40 = 0x40
3810 // - ((0x8080 * 0x8181) / 0xFFFF) >> 8 = 0x4101 >> 8 = 0x41
3811 uint32_t a = 0xFF & (argb_nonpremul >> 24);
3812 uint32_t a16 = a * (0x101 * 0x101);
3813
3814 uint32_t r = 0xFF & (argb_nonpremul >> 16);
3815 r = ((r * a16) / 0xFFFF) >> 8;
3816 uint32_t g = 0xFF & (argb_nonpremul >> 8);
3817 g = ((g * a16) / 0xFFFF) >> 8;
3818 uint32_t b = 0xFF & (argb_nonpremul >> 0);
3819 b = ((b * a16) / 0xFFFF) >> 8;
3820
3821 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3822}
3823
3824// wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul converts
3825// from premultiplied alpha to non-premultiplied alpha.
3826static inline uint32_t //
3827wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
3828 wuffs_base__color_u32_argb_premul c) {
3829 uint32_t a = 0xFF & (c >> 24);
3830 if (a == 0xFF) {
3831 return c;
3832 } else if (a == 0) {
3833 return 0;
3834 }
3835 uint32_t a16 = a * 0x101;
3836
3837 uint32_t r = 0xFF & (c >> 16);
3838 r = ((r * (0x101 * 0xFFFF)) / a16) >> 8;
3839 uint32_t g = 0xFF & (c >> 8);
3840 g = ((g * (0x101 * 0xFFFF)) / a16) >> 8;
3841 uint32_t b = 0xFF & (c >> 0);
3842 b = ((b * (0x101 * 0xFFFF)) / a16) >> 8;
3843
3844 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3845}
3846
3847// wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul converts
3848// from 4x16LE non-premultiplied alpha to 4x8 premultiplied alpha.
3849static inline wuffs_base__color_u32_argb_premul //
3850wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
3851 uint64_t argb_nonpremul) {
3852 uint32_t a16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 48)));
3853
3854 uint32_t r16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 32)));
3855 r16 = (r16 * a16) / 0xFFFF;
3856 uint32_t g16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 16)));
3857 g16 = (g16 * a16) / 0xFFFF;
3858 uint32_t b16 = ((uint32_t)(0xFFFF & (argb_nonpremul >> 0)));
3859 b16 = (b16 * a16) / 0xFFFF;
3860
3861 return ((a16 >> 8) << 24) | ((r16 >> 8) << 16) | ((g16 >> 8) << 8) |
3862 ((b16 >> 8) << 0);
3863}
3864
3865// wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul converts
3866// from 4x8 premultiplied alpha to 4x16LE non-premultiplied alpha.
3867static inline uint64_t //
3868wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
3869 wuffs_base__color_u32_argb_premul c) {
3870 uint32_t a = 0xFF & (c >> 24);
3871 if (a == 0xFF) {
3872 uint64_t r16 = 0x101 * (0xFF & (c >> 16));
3873 uint64_t g16 = 0x101 * (0xFF & (c >> 8));
3874 uint64_t b16 = 0x101 * (0xFF & (c >> 0));
3875 return 0xFFFF000000000000u | (r16 << 32) | (g16 << 16) | (b16 << 0);
3876 } else if (a == 0) {
3877 return 0;
3878 }
3879 uint64_t a16 = a * 0x101;
3880
3881 uint64_t r = 0xFF & (c >> 16);
3882 uint64_t r16 = (r * (0x101 * 0xFFFF)) / a16;
3883 uint64_t g = 0xFF & (c >> 8);
3884 uint64_t g16 = (g * (0x101 * 0xFFFF)) / a16;
3885 uint64_t b = 0xFF & (c >> 0);
3886 uint64_t b16 = (b * (0x101 * 0xFFFF)) / a16;
3887
3888 return (a16 << 48) | (r16 << 32) | (g16 << 16) | (b16 << 0);
3889}
3890
3891static inline uint64_t //
3892wuffs_base__color_u32__as__color_u64(uint32_t c) {
3893 uint64_t a16 = 0x101 * (0xFF & (c >> 24));
3894 uint64_t r16 = 0x101 * (0xFF & (c >> 16));
3895 uint64_t g16 = 0x101 * (0xFF & (c >> 8));
3896 uint64_t b16 = 0x101 * (0xFF & (c >> 0));
3897 return (a16 << 48) | (r16 << 32) | (g16 << 16) | (b16 << 0);
3898}
3899
3900static inline uint32_t //
3901wuffs_base__color_u64__as__color_u32(uint64_t c) {
3902 uint32_t a = ((uint32_t)(0xFF & (c >> 56)));
3903 uint32_t r = ((uint32_t)(0xFF & (c >> 40)));
3904 uint32_t g = ((uint32_t)(0xFF & (c >> 24)));
3905 uint32_t b = ((uint32_t)(0xFF & (c >> 8)));
3906 return (a << 24) | (r << 16) | (g << 8) | (b << 0);
3907}
3908
3909// --------
3910
3911typedef uint8_t wuffs_base__pixel_blend;
3912
3913// wuffs_base__pixel_blend encodes how to blend source and destination pixels,
3914// accounting for transparency. It encompasses the Porter-Duff compositing
3915// operators as well as the other blending modes defined by PDF.
3916//
3917// TODO: implement the other modes.
3918#define WUFFS_BASE__PIXEL_BLEND__SRC ((wuffs_base__pixel_blend)0)
3919#define WUFFS_BASE__PIXEL_BLEND__SRC_OVER ((wuffs_base__pixel_blend)1)
3920
3921// --------
3922
3923// wuffs_base__pixel_alpha_transparency is a pixel format's alpha channel
3924// model. It is a property of the pixel format in general, not of a specific
3925// pixel. An RGBA pixel format (with alpha) can still have fully opaque pixels.
3926typedef uint32_t wuffs_base__pixel_alpha_transparency;
3927
3928#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__OPAQUE 0
3929#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NONPREMULTIPLIED_ALPHA 1
3930#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__PREMULTIPLIED_ALPHA 2
3931#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__BINARY_ALPHA 3
3932
3933// Deprecated: use WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NONPREMULTIPLIED_ALPHA
3934// instead.
3935#define WUFFS_BASE__PIXEL_ALPHA_TRANSPARENCY__NON_PREMULTIPLIED_ALPHA 1
3936
3937// --------
3938
3939#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4
3940
3941#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0
3942#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3
3943
3944// A palette is 256 entries × 4 bytes per entry (e.g. BGRA).
3945#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH 1024
3946
3947// wuffs_base__pixel_format encodes the format of the bytes that constitute an
3948// image frame's pixel data.
3949//
3950// See https://github.com/google/wuffs/blob/main/doc/note/pixel-formats.md
3951//
3952// Do not manipulate its bits directly; they are private implementation
3953// details. Use methods such as wuffs_base__pixel_format__num_planes instead.
3954typedef struct wuffs_base__pixel_format__struct {
3955 uint32_t repr;
3956
3957#ifdef __cplusplus
3958 inline bool is_valid() const;
3959 inline uint32_t bits_per_pixel() const;
3960 inline bool is_direct() const;
3961 inline bool is_indexed() const;
3962 inline bool is_interleaved() const;
3963 inline bool is_planar() const;
3964 inline uint32_t num_planes() const;
3965 inline wuffs_base__pixel_alpha_transparency transparency() const;
3966#endif // __cplusplus
3967
3968} wuffs_base__pixel_format;
3969
3970static inline wuffs_base__pixel_format //
3971wuffs_base__make_pixel_format(uint32_t repr) {
3972 wuffs_base__pixel_format f;
3973 f.repr = repr;
3974 return f;
3975}
3976
3977// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid
3978// wuffs_base__pixel_format values are present.
3979
3980#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000
3981
3982#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008
3983
3984#define WUFFS_BASE__PIXEL_FORMAT__Y 0x20000008
3985#define WUFFS_BASE__PIXEL_FORMAT__Y_16LE 0x2000000B
3986#define WUFFS_BASE__PIXEL_FORMAT__Y_16BE 0x2010000B
3987#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x21000008
3988#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x22000008
3989
3990#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x40020888
3991#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x41038888
3992#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x50038888
3993
3994#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x60020888
3995#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x61038888
3996#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x70038888
3997
3998#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x81040008
3999#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x82040008
4000#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x83040008
4001
4002#define WUFFS_BASE__PIXEL_FORMAT__BGR_565 0x80000565
4003#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x80000888
4004#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x81008888
4005#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE 0x8100BBBB
4006#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x82008888
4007#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE 0x8200BBBB
4008#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x83008888
4009#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x90008888
4010
4011#define WUFFS_BASE__PIXEL_FORMAT__RGB 0xA0000888
4012#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0xA1008888
4013#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE 0xA100BBBB
4014#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0xA2008888
4015#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE 0xA200BBBB
4016#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0xA3008888
4017#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0xB0008888
4018
4019#define WUFFS_BASE__PIXEL_FORMAT__CMY 0xC0020888
4020#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0xD0038888
4021
4022extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];
4023
4024static inline bool //
4025wuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) {
4026 return f->repr != 0;
4027}
4028
4029// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per
4030// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.
4031static inline uint32_t //
4032wuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) {
4033 if (((f->repr >> 16) & 0x03) != 0) {
4034 return 0;
4035 }
4036 return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] +
4037 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] +
4038 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] +
4039 wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)];
4040}
4041
4042static inline bool //
4043wuffs_base__pixel_format__is_direct(const wuffs_base__pixel_format* f) {
4044 return ((f->repr >> 18) & 0x01) == 0;
4045}
4046
4047static inline bool //
4048wuffs_base__pixel_format__is_indexed(const wuffs_base__pixel_format* f) {
4049 return ((f->repr >> 18) & 0x01) != 0;
4050}
4051
4052static inline bool //
4053wuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) {
4054 return ((f->repr >> 16) & 0x03) == 0;
4055}
4056
4057static inline bool //
4058wuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) {
4059 return ((f->repr >> 16) & 0x03) != 0;
4060}
4061
4062static inline uint32_t //
4063wuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) {
4064 return ((f->repr >> 16) & 0x03) + 1;
4065}
4066
4067static inline wuffs_base__pixel_alpha_transparency //
4068wuffs_base__pixel_format__transparency(const wuffs_base__pixel_format* f) {
4069 return (wuffs_base__pixel_alpha_transparency)((f->repr >> 24) & 0x03);
4070}
4071
4072#ifdef __cplusplus
4073
4074inline bool //
4075wuffs_base__pixel_format::is_valid() const {
4076 return wuffs_base__pixel_format__is_valid(this);
4077}
4078
4079inline uint32_t //
4080wuffs_base__pixel_format::bits_per_pixel() const {
4081 return wuffs_base__pixel_format__bits_per_pixel(this);
4082}
4083
4084inline bool //
4085wuffs_base__pixel_format::is_direct() const {
4086 return wuffs_base__pixel_format__is_direct(this);
4087}
4088
4089inline bool //
4090wuffs_base__pixel_format::is_indexed() const {
4091 return wuffs_base__pixel_format__is_indexed(this);
4092}
4093
4094inline bool //
4095wuffs_base__pixel_format::is_interleaved() const {
4096 return wuffs_base__pixel_format__is_interleaved(this);
4097}
4098
4099inline bool //
4100wuffs_base__pixel_format::is_planar() const {
4101 return wuffs_base__pixel_format__is_planar(this);
4102}
4103
4104inline uint32_t //
4105wuffs_base__pixel_format::num_planes() const {
4106 return wuffs_base__pixel_format__num_planes(this);
4107}
4108
4109inline wuffs_base__pixel_alpha_transparency //
4110wuffs_base__pixel_format::transparency() const {
4111 return wuffs_base__pixel_format__transparency(this);
4112}
4113
4114#endif // __cplusplus
4115
4116// --------
4117
4118// wuffs_base__pixel_subsampling encodes whether sample values cover one pixel
4119// or cover multiple pixels.
4120//
4121// See https://github.com/google/wuffs/blob/main/doc/note/pixel-subsampling.md
4122//
4123// Do not manipulate its bits directly; they are private implementation
4124// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.
4125typedef struct wuffs_base__pixel_subsampling__struct {
4126 uint32_t repr;
4127
4128#ifdef __cplusplus
4129 inline uint32_t bias_x(uint32_t plane) const;
4130 inline uint32_t denominator_x(uint32_t plane) const;
4131 inline uint32_t bias_y(uint32_t plane) const;
4132 inline uint32_t denominator_y(uint32_t plane) const;
4133#endif // __cplusplus
4134
4135} wuffs_base__pixel_subsampling;
4136
4137static inline wuffs_base__pixel_subsampling //
4138wuffs_base__make_pixel_subsampling(uint32_t repr) {
4139 wuffs_base__pixel_subsampling s;
4140 s.repr = repr;
4141 return s;
4142}
4143
4144#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE 0x00000000
4145
4146#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 0x000000
4147#define WUFFS_BASE__PIXEL_SUBSAMPLING__440 0x010100
4148#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 0x101000
4149#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 0x111100
4150#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 0x303000
4151#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 0x313100
4152
4153static inline uint32_t //
4154wuffs_base__pixel_subsampling__bias_x(const wuffs_base__pixel_subsampling* s,
4155 uint32_t plane) {
4156 uint32_t shift = ((plane & 0x03) * 8) + 6;
4157 return (s->repr >> shift) & 0x03;
4158}
4159
4160static inline uint32_t //
4161wuffs_base__pixel_subsampling__denominator_x(
4162 const wuffs_base__pixel_subsampling* s,
4163 uint32_t plane) {
4164 uint32_t shift = ((plane & 0x03) * 8) + 4;
4165 return ((s->repr >> shift) & 0x03) + 1;
4166}
4167
4168static inline uint32_t //
4169wuffs_base__pixel_subsampling__bias_y(const wuffs_base__pixel_subsampling* s,
4170 uint32_t plane) {
4171 uint32_t shift = ((plane & 0x03) * 8) + 2;
4172 return (s->repr >> shift) & 0x03;
4173}
4174
4175static inline uint32_t //
4176wuffs_base__pixel_subsampling__denominator_y(
4177 const wuffs_base__pixel_subsampling* s,
4178 uint32_t plane) {
4179 uint32_t shift = ((plane & 0x03) * 8) + 0;
4180 return ((s->repr >> shift) & 0x03) + 1;
4181}
4182
4183#ifdef __cplusplus
4184
4185inline uint32_t //
4186wuffs_base__pixel_subsampling::bias_x(uint32_t plane) const {
4187 return wuffs_base__pixel_subsampling__bias_x(this, plane);
4188}
4189
4190inline uint32_t //
4191wuffs_base__pixel_subsampling::denominator_x(uint32_t plane) const {
4192 return wuffs_base__pixel_subsampling__denominator_x(this, plane);
4193}
4194
4195inline uint32_t //
4196wuffs_base__pixel_subsampling::bias_y(uint32_t plane) const {
4197 return wuffs_base__pixel_subsampling__bias_y(this, plane);
4198}
4199
4200inline uint32_t //
4201wuffs_base__pixel_subsampling::denominator_y(uint32_t plane) const {
4202 return wuffs_base__pixel_subsampling__denominator_y(this, plane);
4203}
4204
4205#endif // __cplusplus
4206
4207// --------
4208
4209typedef struct wuffs_base__pixel_config__struct {
4210 // Do not access the private_impl's fields directly. There is no API/ABI
4211 // compatibility or safety guarantee if you do so.
4212 struct {
4213 wuffs_base__pixel_format pixfmt;
4214 wuffs_base__pixel_subsampling pixsub;
4215 uint32_t width;
4216 uint32_t height;
4217 } private_impl;
4218
4219#ifdef __cplusplus
4220 inline void set(uint32_t pixfmt_repr,
4221 uint32_t pixsub_repr,
4222 uint32_t width,
4223 uint32_t height);
4224 inline void invalidate();
4225 inline bool is_valid() const;
4226 inline wuffs_base__pixel_format pixel_format() const;
4227 inline wuffs_base__pixel_subsampling pixel_subsampling() const;
4228 inline wuffs_base__rect_ie_u32 bounds() const;
4229 inline uint32_t width() const;
4230 inline uint32_t height() const;
4231 inline uint64_t pixbuf_len() const;
4232#endif // __cplusplus
4233
4234} wuffs_base__pixel_config;
4235
4236static inline wuffs_base__pixel_config //
4237wuffs_base__null_pixel_config() {
4238 wuffs_base__pixel_config ret;
4239 ret.private_impl.pixfmt.repr = 0;
4240 ret.private_impl.pixsub.repr = 0;
4241 ret.private_impl.width = 0;
4242 ret.private_impl.height = 0;
4243 return ret;
4244}
4245
4246// TODO: Should this function return bool? An error type?
4247static inline void //
4248wuffs_base__pixel_config__set(wuffs_base__pixel_config* c,
4249 uint32_t pixfmt_repr,
4250 uint32_t pixsub_repr,
4251 uint32_t width,
4252 uint32_t height) {
4253 if (!c) {
4254 return;
4255 }
4256 if (pixfmt_repr) {
4257 uint64_t wh = ((uint64_t)width) * ((uint64_t)height);
4258 // TODO: handle things other than 1 byte per pixel.
4259 if (wh <= ((uint64_t)SIZE_MAX)) {
4260 c->private_impl.pixfmt.repr = pixfmt_repr;
4261 c->private_impl.pixsub.repr = pixsub_repr;
4262 c->private_impl.width = width;
4263 c->private_impl.height = height;
4264 return;
4265 }
4266 }
4267
4268 c->private_impl.pixfmt.repr = 0;
4269 c->private_impl.pixsub.repr = 0;
4270 c->private_impl.width = 0;
4271 c->private_impl.height = 0;
4272}
4273
4274static inline void //
4275wuffs_base__pixel_config__invalidate(wuffs_base__pixel_config* c) {
4276 if (c) {
4277 c->private_impl.pixfmt.repr = 0;
4278 c->private_impl.pixsub.repr = 0;
4279 c->private_impl.width = 0;
4280 c->private_impl.height = 0;
4281 }
4282}
4283
4284static inline bool //
4285wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {
4286 return c && c->private_impl.pixfmt.repr;
4287}
4288
4289static inline wuffs_base__pixel_format //
4290wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {
4291 return c ? c->private_impl.pixfmt : wuffs_base__make_pixel_format(0);
4292}
4293
4294static inline wuffs_base__pixel_subsampling //
4295wuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {
4296 return c ? c->private_impl.pixsub : wuffs_base__make_pixel_subsampling(0);
4297}
4298
4299static inline wuffs_base__rect_ie_u32 //
4300wuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {
4301 if (c) {
4302 wuffs_base__rect_ie_u32 ret;
4303 ret.min_incl_x = 0;
4304 ret.min_incl_y = 0;
4305 ret.max_excl_x = c->private_impl.width;
4306 ret.max_excl_y = c->private_impl.height;
4307 return ret;
4308 }
4309
4310 wuffs_base__rect_ie_u32 ret;
4311 ret.min_incl_x = 0;
4312 ret.min_incl_y = 0;
4313 ret.max_excl_x = 0;
4314 ret.max_excl_y = 0;
4315 return ret;
4316}
4317
4318static inline uint32_t //
4319wuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {
4320 return c ? c->private_impl.width : 0;
4321}
4322
4323static inline uint32_t //
4324wuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {
4325 return c ? c->private_impl.height : 0;
4326}
4327
4328// TODO: this is the right API for planar (not interleaved) pixbufs? Should it
4329// allow decoding into a color model different from the format's intrinsic one?
4330// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?
4331static inline uint64_t //
4332wuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {
4333 if (!c) {
4334 return 0;
4335 }
4336 if (wuffs_base__pixel_format__is_planar(&c->private_impl.pixfmt)) {
4337 // TODO: support planar pixel formats, concious of pixel subsampling.
4338 return 0;
4339 }
4340 uint32_t bits_per_pixel =
4341 wuffs_base__pixel_format__bits_per_pixel(&c->private_impl.pixfmt);
4342 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4343 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4344 return 0;
4345 }
4346 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4347
4348 uint64_t n =
4349 ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);
4350 if (n > (UINT64_MAX / bytes_per_pixel)) {
4351 return 0;
4352 }
4353 n *= bytes_per_pixel;
4354
4355 if (wuffs_base__pixel_format__is_indexed(&c->private_impl.pixfmt)) {
4356 if (n >
4357 (UINT64_MAX - WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH)) {
4358 return 0;
4359 }
4360 n += WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4361 }
4362
4363 return n;
4364}
4365
4366#ifdef __cplusplus
4367
4368inline void //
4369wuffs_base__pixel_config::set(uint32_t pixfmt_repr,
4370 uint32_t pixsub_repr,
4371 uint32_t width,
4372 uint32_t height) {
4373 wuffs_base__pixel_config__set(this, pixfmt_repr, pixsub_repr, width, height);
4374}
4375
4376inline void //
4377wuffs_base__pixel_config::invalidate() {
4378 wuffs_base__pixel_config__invalidate(this);
4379}
4380
4381inline bool //
4382wuffs_base__pixel_config::is_valid() const {
4383 return wuffs_base__pixel_config__is_valid(this);
4384}
4385
4386inline wuffs_base__pixel_format //
4387wuffs_base__pixel_config::pixel_format() const {
4388 return wuffs_base__pixel_config__pixel_format(this);
4389}
4390
4391inline wuffs_base__pixel_subsampling //
4392wuffs_base__pixel_config::pixel_subsampling() const {
4393 return wuffs_base__pixel_config__pixel_subsampling(this);
4394}
4395
4396inline wuffs_base__rect_ie_u32 //
4397wuffs_base__pixel_config::bounds() const {
4398 return wuffs_base__pixel_config__bounds(this);
4399}
4400
4401inline uint32_t //
4402wuffs_base__pixel_config::width() const {
4403 return wuffs_base__pixel_config__width(this);
4404}
4405
4406inline uint32_t //
4407wuffs_base__pixel_config::height() const {
4408 return wuffs_base__pixel_config__height(this);
4409}
4410
4411inline uint64_t //
4412wuffs_base__pixel_config::pixbuf_len() const {
4413 return wuffs_base__pixel_config__pixbuf_len(this);
4414}
4415
4416#endif // __cplusplus
4417
4418// --------
4419
4420typedef struct wuffs_base__image_config__struct {
4421 wuffs_base__pixel_config pixcfg;
4422
4423 // Do not access the private_impl's fields directly. There is no API/ABI
4424 // compatibility or safety guarantee if you do so.
4425 struct {
4426 uint64_t first_frame_io_position;
4427 bool first_frame_is_opaque;
4428 } private_impl;
4429
4430#ifdef __cplusplus
4431 inline void set(uint32_t pixfmt_repr,
4432 uint32_t pixsub_repr,
4433 uint32_t width,
4434 uint32_t height,
4435 uint64_t first_frame_io_position,
4436 bool first_frame_is_opaque);
4437 inline void invalidate();
4438 inline bool is_valid() const;
4439 inline uint64_t first_frame_io_position() const;
4440 inline bool first_frame_is_opaque() const;
4441#endif // __cplusplus
4442
4443} wuffs_base__image_config;
4444
4445static inline wuffs_base__image_config //
4446wuffs_base__null_image_config() {
4447 wuffs_base__image_config ret;
4448 ret.pixcfg = wuffs_base__null_pixel_config();
4449 ret.private_impl.first_frame_io_position = 0;
4450 ret.private_impl.first_frame_is_opaque = false;
4451 return ret;
4452}
4453
4454// TODO: Should this function return bool? An error type?
4455static inline void //
4456wuffs_base__image_config__set(wuffs_base__image_config* c,
4457 uint32_t pixfmt_repr,
4458 uint32_t pixsub_repr,
4459 uint32_t width,
4460 uint32_t height,
4461 uint64_t first_frame_io_position,
4462 bool first_frame_is_opaque) {
4463 if (!c) {
4464 return;
4465 }
4466 if (pixfmt_repr) {
4467 c->pixcfg.private_impl.pixfmt.repr = pixfmt_repr;
4468 c->pixcfg.private_impl.pixsub.repr = pixsub_repr;
4469 c->pixcfg.private_impl.width = width;
4470 c->pixcfg.private_impl.height = height;
4471 c->private_impl.first_frame_io_position = first_frame_io_position;
4472 c->private_impl.first_frame_is_opaque = first_frame_is_opaque;
4473 return;
4474 }
4475
4476 c->pixcfg.private_impl.pixfmt.repr = 0;
4477 c->pixcfg.private_impl.pixsub.repr = 0;
4478 c->pixcfg.private_impl.width = 0;
4479 c->pixcfg.private_impl.height = 0;
4480 c->private_impl.first_frame_io_position = 0;
4481 c->private_impl.first_frame_is_opaque = 0;
4482}
4483
4484static inline void //
4485wuffs_base__image_config__invalidate(wuffs_base__image_config* c) {
4486 if (c) {
4487 c->pixcfg.private_impl.pixfmt.repr = 0;
4488 c->pixcfg.private_impl.pixsub.repr = 0;
4489 c->pixcfg.private_impl.width = 0;
4490 c->pixcfg.private_impl.height = 0;
4491 c->private_impl.first_frame_io_position = 0;
4492 c->private_impl.first_frame_is_opaque = 0;
4493 }
4494}
4495
4496static inline bool //
4497wuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {
4498 return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));
4499}
4500
4501static inline uint64_t //
4502wuffs_base__image_config__first_frame_io_position(
4503 const wuffs_base__image_config* c) {
4504 return c ? c->private_impl.first_frame_io_position : 0;
4505}
4506
4507static inline bool //
4508wuffs_base__image_config__first_frame_is_opaque(
4509 const wuffs_base__image_config* c) {
4510 return c ? c->private_impl.first_frame_is_opaque : false;
4511}
4512
4513#ifdef __cplusplus
4514
4515inline void //
4516wuffs_base__image_config::set(uint32_t pixfmt_repr,
4517 uint32_t pixsub_repr,
4518 uint32_t width,
4519 uint32_t height,
4520 uint64_t first_frame_io_position,
4521 bool first_frame_is_opaque) {
4522 wuffs_base__image_config__set(this, pixfmt_repr, pixsub_repr, width, height,
4523 first_frame_io_position, first_frame_is_opaque);
4524}
4525
4526inline void //
4527wuffs_base__image_config::invalidate() {
4528 wuffs_base__image_config__invalidate(this);
4529}
4530
4531inline bool //
4532wuffs_base__image_config::is_valid() const {
4533 return wuffs_base__image_config__is_valid(this);
4534}
4535
4536inline uint64_t //
4537wuffs_base__image_config::first_frame_io_position() const {
4538 return wuffs_base__image_config__first_frame_io_position(this);
4539}
4540
4541inline bool //
4542wuffs_base__image_config::first_frame_is_opaque() const {
4543 return wuffs_base__image_config__first_frame_is_opaque(this);
4544}
4545
4546#endif // __cplusplus
4547
4548// --------
4549
4550// wuffs_base__animation_disposal encodes, for an animated image, how to
4551// dispose of a frame after displaying it:
4552// - None means to draw the next frame on top of this one.
4553// - Restore Background means to clear the frame's dirty rectangle to "the
4554// background color" (in practice, this means transparent black) before
4555// drawing the next frame.
4556// - Restore Previous means to undo the current frame, so that the next frame
4557// is drawn on top of the previous one.
4558typedef uint8_t wuffs_base__animation_disposal;
4559
4560#define WUFFS_BASE__ANIMATION_DISPOSAL__NONE ((wuffs_base__animation_disposal)0)
4561#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND \
4562 ((wuffs_base__animation_disposal)1)
4563#define WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_PREVIOUS \
4564 ((wuffs_base__animation_disposal)2)
4565
4566// --------
4567
4568typedef struct wuffs_base__frame_config__struct {
4569 // Do not access the private_impl's fields directly. There is no API/ABI
4570 // compatibility or safety guarantee if you do so.
4571 struct {
4572 wuffs_base__rect_ie_u32 bounds;
4573 wuffs_base__flicks duration;
4574 uint64_t index;
4575 uint64_t io_position;
4576 wuffs_base__animation_disposal disposal;
4577 bool opaque_within_bounds;
4578 bool overwrite_instead_of_blend;
4579 wuffs_base__color_u32_argb_premul background_color;
4580 } private_impl;
4581
4582#ifdef __cplusplus
4583 inline void set(wuffs_base__rect_ie_u32 bounds,
4584 wuffs_base__flicks duration,
4585 uint64_t index,
4586 uint64_t io_position,
4587 wuffs_base__animation_disposal disposal,
4588 bool opaque_within_bounds,
4589 bool overwrite_instead_of_blend,
4590 wuffs_base__color_u32_argb_premul background_color);
4591 inline wuffs_base__rect_ie_u32 bounds() const;
4592 inline uint32_t width() const;
4593 inline uint32_t height() const;
4594 inline wuffs_base__flicks duration() const;
4595 inline uint64_t index() const;
4596 inline uint64_t io_position() const;
4597 inline wuffs_base__animation_disposal disposal() const;
4598 inline bool opaque_within_bounds() const;
4599 inline bool overwrite_instead_of_blend() const;
4600 inline wuffs_base__color_u32_argb_premul background_color() const;
4601#endif // __cplusplus
4602
4603} wuffs_base__frame_config;
4604
4605static inline wuffs_base__frame_config //
4606wuffs_base__null_frame_config() {
4607 wuffs_base__frame_config ret;
4608 ret.private_impl.bounds = wuffs_base__make_rect_ie_u32(0, 0, 0, 0);
4609 ret.private_impl.duration = 0;
4610 ret.private_impl.index = 0;
4611 ret.private_impl.io_position = 0;
4612 ret.private_impl.disposal = 0;
4613 ret.private_impl.opaque_within_bounds = false;
4614 ret.private_impl.overwrite_instead_of_blend = false;
4615 return ret;
4616}
4617
4618static inline void //
4619wuffs_base__frame_config__set(
4620 wuffs_base__frame_config* c,
4621 wuffs_base__rect_ie_u32 bounds,
4622 wuffs_base__flicks duration,
4623 uint64_t index,
4624 uint64_t io_position,
4625 wuffs_base__animation_disposal disposal,
4626 bool opaque_within_bounds,
4627 bool overwrite_instead_of_blend,
4628 wuffs_base__color_u32_argb_premul background_color) {
4629 if (!c) {
4630 return;
4631 }
4632
4633 c->private_impl.bounds = bounds;
4634 c->private_impl.duration = duration;
4635 c->private_impl.index = index;
4636 c->private_impl.io_position = io_position;
4637 c->private_impl.disposal = disposal;
4638 c->private_impl.opaque_within_bounds = opaque_within_bounds;
4639 c->private_impl.overwrite_instead_of_blend = overwrite_instead_of_blend;
4640 c->private_impl.background_color = background_color;
4641}
4642
4643static inline wuffs_base__rect_ie_u32 //
4644wuffs_base__frame_config__bounds(const wuffs_base__frame_config* c) {
4645 if (c) {
4646 return c->private_impl.bounds;
4647 }
4648
4649 wuffs_base__rect_ie_u32 ret;
4650 ret.min_incl_x = 0;
4651 ret.min_incl_y = 0;
4652 ret.max_excl_x = 0;
4653 ret.max_excl_y = 0;
4654 return ret;
4655}
4656
4657static inline uint32_t //
4658wuffs_base__frame_config__width(const wuffs_base__frame_config* c) {
4659 return c ? wuffs_base__rect_ie_u32__width(&c->private_impl.bounds) : 0;
4660}
4661
4662static inline uint32_t //
4663wuffs_base__frame_config__height(const wuffs_base__frame_config* c) {
4664 return c ? wuffs_base__rect_ie_u32__height(&c->private_impl.bounds) : 0;
4665}
4666
4667// wuffs_base__frame_config__duration returns the amount of time to display
4668// this frame. Zero means to display forever - a still (non-animated) image.
4669static inline wuffs_base__flicks //
4670wuffs_base__frame_config__duration(const wuffs_base__frame_config* c) {
4671 return c ? c->private_impl.duration : 0;
4672}
4673
4674// wuffs_base__frame_config__index returns the index of this frame. The first
4675// frame in an image has index 0, the second frame has index 1, and so on.
4676static inline uint64_t //
4677wuffs_base__frame_config__index(const wuffs_base__frame_config* c) {
4678 return c ? c->private_impl.index : 0;
4679}
4680
4681// wuffs_base__frame_config__io_position returns the I/O stream position before
4682// the frame config.
4683static inline uint64_t //
4684wuffs_base__frame_config__io_position(const wuffs_base__frame_config* c) {
4685 return c ? c->private_impl.io_position : 0;
4686}
4687
4688// wuffs_base__frame_config__disposal returns, for an animated image, how to
4689// dispose of this frame after displaying it.
4690static inline wuffs_base__animation_disposal //
4691wuffs_base__frame_config__disposal(const wuffs_base__frame_config* c) {
4692 return c ? c->private_impl.disposal : 0;
4693}
4694
4695// wuffs_base__frame_config__opaque_within_bounds returns whether all pixels
4696// within the frame's bounds are fully opaque. It makes no claim about pixels
4697// outside the frame bounds but still inside the overall image. The two
4698// bounding rectangles can differ for animated images.
4699//
4700// Its semantics are conservative. It is valid for a fully opaque frame to have
4701// this value be false: a false negative.
4702//
4703// If true, drawing the frame with WUFFS_BASE__PIXEL_BLEND__SRC and
4704// WUFFS_BASE__PIXEL_BLEND__SRC_OVER should be equivalent, in terms of
4705// resultant pixels, but the former may be faster.
4706static inline bool //
4707wuffs_base__frame_config__opaque_within_bounds(
4708 const wuffs_base__frame_config* c) {
4709 return c && c->private_impl.opaque_within_bounds;
4710}
4711
4712// wuffs_base__frame_config__overwrite_instead_of_blend returns, for an
4713// animated image, whether to ignore the previous image state (within the frame
4714// bounds) when drawing this incremental frame. Equivalently, whether to use
4715// WUFFS_BASE__PIXEL_BLEND__SRC instead of WUFFS_BASE__PIXEL_BLEND__SRC_OVER.
4716//
4717// The WebP spec (https://developers.google.com/speed/webp/docs/riff_container)
4718// calls this the "Blending method" bit. WebP's "Do not blend" corresponds to
4719// Wuffs' "overwrite_instead_of_blend".
4720static inline bool //
4721wuffs_base__frame_config__overwrite_instead_of_blend(
4722 const wuffs_base__frame_config* c) {
4723 return c && c->private_impl.overwrite_instead_of_blend;
4724}
4725
4726static inline wuffs_base__color_u32_argb_premul //
4727wuffs_base__frame_config__background_color(const wuffs_base__frame_config* c) {
4728 return c ? c->private_impl.background_color : 0;
4729}
4730
4731#ifdef __cplusplus
4732
4733inline void //
4734wuffs_base__frame_config::set(
4735 wuffs_base__rect_ie_u32 bounds,
4736 wuffs_base__flicks duration,
4737 uint64_t index,
4738 uint64_t io_position,
4739 wuffs_base__animation_disposal disposal,
4740 bool opaque_within_bounds,
4741 bool overwrite_instead_of_blend,
4742 wuffs_base__color_u32_argb_premul background_color) {
4743 wuffs_base__frame_config__set(this, bounds, duration, index, io_position,
4744 disposal, opaque_within_bounds,
4745 overwrite_instead_of_blend, background_color);
4746}
4747
4748inline wuffs_base__rect_ie_u32 //
4749wuffs_base__frame_config::bounds() const {
4750 return wuffs_base__frame_config__bounds(this);
4751}
4752
4753inline uint32_t //
4754wuffs_base__frame_config::width() const {
4755 return wuffs_base__frame_config__width(this);
4756}
4757
4758inline uint32_t //
4759wuffs_base__frame_config::height() const {
4760 return wuffs_base__frame_config__height(this);
4761}
4762
4763inline wuffs_base__flicks //
4764wuffs_base__frame_config::duration() const {
4765 return wuffs_base__frame_config__duration(this);
4766}
4767
4768inline uint64_t //
4769wuffs_base__frame_config::index() const {
4770 return wuffs_base__frame_config__index(this);
4771}
4772
4773inline uint64_t //
4774wuffs_base__frame_config::io_position() const {
4775 return wuffs_base__frame_config__io_position(this);
4776}
4777
4778inline wuffs_base__animation_disposal //
4779wuffs_base__frame_config::disposal() const {
4780 return wuffs_base__frame_config__disposal(this);
4781}
4782
4783inline bool //
4784wuffs_base__frame_config::opaque_within_bounds() const {
4785 return wuffs_base__frame_config__opaque_within_bounds(this);
4786}
4787
4788inline bool //
4789wuffs_base__frame_config::overwrite_instead_of_blend() const {
4790 return wuffs_base__frame_config__overwrite_instead_of_blend(this);
4791}
4792
4793inline wuffs_base__color_u32_argb_premul //
4794wuffs_base__frame_config::background_color() const {
4795 return wuffs_base__frame_config__background_color(this);
4796}
4797
4798#endif // __cplusplus
4799
4800// --------
4801
4802typedef struct wuffs_base__pixel_buffer__struct {
4803 wuffs_base__pixel_config pixcfg;
4804
4805 // Do not access the private_impl's fields directly. There is no API/ABI
4806 // compatibility or safety guarantee if you do so.
4807 struct {
4808 wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];
4809 // TODO: color spaces.
4810 } private_impl;
4811
4812#ifdef __cplusplus
4813 inline wuffs_base__status set_interleaved(
4814 const wuffs_base__pixel_config* pixcfg,
4815 wuffs_base__table_u8 primary_memory,
4816 wuffs_base__slice_u8 palette_memory);
4817 inline wuffs_base__status set_from_slice(
4818 const wuffs_base__pixel_config* pixcfg,
4819 wuffs_base__slice_u8 pixbuf_memory);
4820 inline wuffs_base__status set_from_table(
4821 const wuffs_base__pixel_config* pixcfg,
4822 wuffs_base__table_u8 primary_memory);
4823 inline wuffs_base__slice_u8 palette();
4824 inline wuffs_base__slice_u8 palette_or_else(wuffs_base__slice_u8 fallback);
4825 inline wuffs_base__pixel_format pixel_format() const;
4826 inline wuffs_base__table_u8 plane(uint32_t p);
4827 inline wuffs_base__color_u32_argb_premul color_u32_at(uint32_t x,
4828 uint32_t y) const;
4829 inline wuffs_base__status set_color_u32_at(
4830 uint32_t x,
4831 uint32_t y,
4832 wuffs_base__color_u32_argb_premul color);
4833 inline wuffs_base__status set_color_u32_fill_rect(
4834 wuffs_base__rect_ie_u32 rect,
4835 wuffs_base__color_u32_argb_premul color);
4836#endif // __cplusplus
4837
4838} wuffs_base__pixel_buffer;
4839
4840static inline wuffs_base__pixel_buffer //
4841wuffs_base__null_pixel_buffer() {
4842 wuffs_base__pixel_buffer ret;
4843 ret.pixcfg = wuffs_base__null_pixel_config();
4844 ret.private_impl.planes[0] = wuffs_base__empty_table_u8();
4845 ret.private_impl.planes[1] = wuffs_base__empty_table_u8();
4846 ret.private_impl.planes[2] = wuffs_base__empty_table_u8();
4847 ret.private_impl.planes[3] = wuffs_base__empty_table_u8();
4848 return ret;
4849}
4850
4851static inline wuffs_base__status //
4852wuffs_base__pixel_buffer__set_interleaved(
4853 wuffs_base__pixel_buffer* pb,
4854 const wuffs_base__pixel_config* pixcfg,
4855 wuffs_base__table_u8 primary_memory,
4856 wuffs_base__slice_u8 palette_memory) {
4857 if (!pb) {
4858 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4859 }
4860 memset(pb, 0, sizeof(*pb));
4861 if (!pixcfg ||
4862 wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4863 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4864 }
4865 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt) &&
4866 (palette_memory.len <
4867 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH)) {
4868 return wuffs_base__make_status(
4869 wuffs_base__error__bad_argument_length_too_short);
4870 }
4871 uint32_t bits_per_pixel =
4872 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4873 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4874 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4875 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4876 }
4877 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4878
4879 uint64_t width_in_bytes =
4880 ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
4881 if ((width_in_bytes > primary_memory.width) ||
4882 (pixcfg->private_impl.height > primary_memory.height)) {
4883 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4884 }
4885
4886 pb->pixcfg = *pixcfg;
4887 pb->private_impl.planes[0] = primary_memory;
4888 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt)) {
4889 wuffs_base__table_u8* tab =
4890 &pb->private_impl
4891 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4892 tab->ptr = palette_memory.ptr;
4893 tab->width = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4894 tab->height = 1;
4895 tab->stride = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4896 }
4897 return wuffs_base__make_status(NULL);
4898}
4899
4900static inline wuffs_base__status //
4901wuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* pb,
4902 const wuffs_base__pixel_config* pixcfg,
4903 wuffs_base__slice_u8 pixbuf_memory) {
4904 if (!pb) {
4905 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4906 }
4907 memset(pb, 0, sizeof(*pb));
4908 if (!pixcfg) {
4909 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4910 }
4911 if (wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4912 // TODO: support planar pixel formats, concious of pixel subsampling.
4913 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4914 }
4915 uint32_t bits_per_pixel =
4916 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4917 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4918 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4919 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4920 }
4921 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4922
4923 uint8_t* ptr = pixbuf_memory.ptr;
4924 uint64_t len = pixbuf_memory.len;
4925 if (wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt)) {
4926 // Split a WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH byte
4927 // chunk (1024 bytes = 256 palette entries × 4 bytes per entry) from the
4928 // start of pixbuf_memory. We split from the start, not the end, so that
4929 // the both chunks' pointers have the same alignment as the original
4930 // pointer, up to an alignment of 1024.
4931 if (len < WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
4932 return wuffs_base__make_status(
4933 wuffs_base__error__bad_argument_length_too_short);
4934 }
4935 wuffs_base__table_u8* tab =
4936 &pb->private_impl
4937 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
4938 tab->ptr = ptr;
4939 tab->width = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4940 tab->height = 1;
4941 tab->stride = WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4942 ptr += WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4943 len -= WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH;
4944 }
4945
4946 uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *
4947 ((uint64_t)pixcfg->private_impl.height);
4948 size_t width = (size_t)(pixcfg->private_impl.width);
4949 if ((wh > (UINT64_MAX / bytes_per_pixel)) ||
4950 (width > (SIZE_MAX / bytes_per_pixel))) {
4951 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4952 }
4953 wh *= bytes_per_pixel;
4954 width = ((size_t)(width * bytes_per_pixel));
4955 if (wh > len) {
4956 return wuffs_base__make_status(
4957 wuffs_base__error__bad_argument_length_too_short);
4958 }
4959
4960 pb->pixcfg = *pixcfg;
4961 wuffs_base__table_u8* tab = &pb->private_impl.planes[0];
4962 tab->ptr = ptr;
4963 tab->width = width;
4964 tab->height = pixcfg->private_impl.height;
4965 tab->stride = width;
4966 return wuffs_base__make_status(NULL);
4967}
4968
4969// Deprecated: does not handle indexed pixel configurations. Use
4970// wuffs_base__pixel_buffer__set_interleaved instead.
4971static inline wuffs_base__status //
4972wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* pb,
4973 const wuffs_base__pixel_config* pixcfg,
4974 wuffs_base__table_u8 primary_memory) {
4975 if (!pb) {
4976 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
4977 }
4978 memset(pb, 0, sizeof(*pb));
4979 if (!pixcfg ||
4980 wuffs_base__pixel_format__is_indexed(&pixcfg->private_impl.pixfmt) ||
4981 wuffs_base__pixel_format__is_planar(&pixcfg->private_impl.pixfmt)) {
4982 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4983 }
4984 uint32_t bits_per_pixel =
4985 wuffs_base__pixel_format__bits_per_pixel(&pixcfg->private_impl.pixfmt);
4986 if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
4987 // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
4988 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
4989 }
4990 uint64_t bytes_per_pixel = bits_per_pixel / 8;
4991
4992 uint64_t width_in_bytes =
4993 ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
4994 if ((width_in_bytes > primary_memory.width) ||
4995 (pixcfg->private_impl.height > primary_memory.height)) {
4996 return wuffs_base__make_status(wuffs_base__error__bad_argument);
4997 }
4998
4999 pb->pixcfg = *pixcfg;
5000 pb->private_impl.planes[0] = primary_memory;
5001 return wuffs_base__make_status(NULL);
5002}
5003
5004// wuffs_base__pixel_buffer__palette returns the palette color data. If
5005// non-empty, it will have length
5006// WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH.
5007static inline wuffs_base__slice_u8 //
5008wuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* pb) {
5009 if (pb &&
5010 wuffs_base__pixel_format__is_indexed(&pb->pixcfg.private_impl.pixfmt)) {
5011 wuffs_base__table_u8* tab =
5012 &pb->private_impl
5013 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
5014 if ((tab->width ==
5015 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) &&
5016 (tab->height == 1)) {
5017 return wuffs_base__make_slice_u8(
5018 tab->ptr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH);
5019 }
5020 }
5021 return wuffs_base__make_slice_u8(NULL, 0);
5022}
5023
5024static inline wuffs_base__slice_u8 //
5025wuffs_base__pixel_buffer__palette_or_else(wuffs_base__pixel_buffer* pb,
5026 wuffs_base__slice_u8 fallback) {
5027 if (pb &&
5028 wuffs_base__pixel_format__is_indexed(&pb->pixcfg.private_impl.pixfmt)) {
5029 wuffs_base__table_u8* tab =
5030 &pb->private_impl
5031 .planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];
5032 if ((tab->width ==
5033 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) &&
5034 (tab->height == 1)) {
5035 return wuffs_base__make_slice_u8(
5036 tab->ptr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH);
5037 }
5038 }
5039 return fallback;
5040}
5041
5042static inline wuffs_base__pixel_format //
5043wuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* pb) {
5044 if (pb) {
5045 return pb->pixcfg.private_impl.pixfmt;
5046 }
5047 return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__INVALID);
5048}
5049
5050static inline wuffs_base__table_u8 //
5051wuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* pb, uint32_t p) {
5052 if (pb && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {
5053 return pb->private_impl.planes[p];
5054 }
5055
5056 wuffs_base__table_u8 ret;
5057 ret.ptr = NULL;
5058 ret.width = 0;
5059 ret.height = 0;
5060 ret.stride = 0;
5061 return ret;
5062}
5063
5064WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
5065wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
5066 uint32_t x,
5067 uint32_t y);
5068
5069WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5070wuffs_base__pixel_buffer__set_color_u32_at(
5071 wuffs_base__pixel_buffer* pb,
5072 uint32_t x,
5073 uint32_t y,
5074 wuffs_base__color_u32_argb_premul color);
5075
5076WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5077wuffs_base__pixel_buffer__set_color_u32_fill_rect(
5078 wuffs_base__pixel_buffer* pb,
5079 wuffs_base__rect_ie_u32 rect,
5080 wuffs_base__color_u32_argb_premul color);
5081
5082#ifdef __cplusplus
5083
5084inline wuffs_base__status //
5085wuffs_base__pixel_buffer::set_interleaved(
5086 const wuffs_base__pixel_config* pixcfg_arg,
5087 wuffs_base__table_u8 primary_memory,
5088 wuffs_base__slice_u8 palette_memory) {
5089 return wuffs_base__pixel_buffer__set_interleaved(
5090 this, pixcfg_arg, primary_memory, palette_memory);
5091}
5092
5093inline wuffs_base__status //
5094wuffs_base__pixel_buffer::set_from_slice(
5095 const wuffs_base__pixel_config* pixcfg_arg,
5096 wuffs_base__slice_u8 pixbuf_memory) {
5097 return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg_arg,
5098 pixbuf_memory);
5099}
5100
5101inline wuffs_base__status //
5102wuffs_base__pixel_buffer::set_from_table(
5103 const wuffs_base__pixel_config* pixcfg_arg,
5104 wuffs_base__table_u8 primary_memory) {
5105 return wuffs_base__pixel_buffer__set_from_table(this, pixcfg_arg,
5106 primary_memory);
5107}
5108
5109inline wuffs_base__slice_u8 //
5110wuffs_base__pixel_buffer::palette() {
5111 return wuffs_base__pixel_buffer__palette(this);
5112}
5113
5114inline wuffs_base__slice_u8 //
5115wuffs_base__pixel_buffer::palette_or_else(wuffs_base__slice_u8 fallback) {
5116 return wuffs_base__pixel_buffer__palette_or_else(this, fallback);
5117}
5118
5119inline wuffs_base__pixel_format //
5120wuffs_base__pixel_buffer::pixel_format() const {
5121 return wuffs_base__pixel_buffer__pixel_format(this);
5122}
5123
5124inline wuffs_base__table_u8 //
5125wuffs_base__pixel_buffer::plane(uint32_t p) {
5126 return wuffs_base__pixel_buffer__plane(this, p);
5127}
5128
5129inline wuffs_base__color_u32_argb_premul //
5130wuffs_base__pixel_buffer::color_u32_at(uint32_t x, uint32_t y) const {
5131 return wuffs_base__pixel_buffer__color_u32_at(this, x, y);
5132}
5133
5134WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5135wuffs_base__pixel_buffer__set_color_u32_fill_rect(
5136 wuffs_base__pixel_buffer* pb,
5137 wuffs_base__rect_ie_u32 rect,
5138 wuffs_base__color_u32_argb_premul color);
5139
5140inline wuffs_base__status //
5141wuffs_base__pixel_buffer::set_color_u32_at(
5142 uint32_t x,
5143 uint32_t y,
5144 wuffs_base__color_u32_argb_premul color) {
5145 return wuffs_base__pixel_buffer__set_color_u32_at(this, x, y, color);
5146}
5147
5148inline wuffs_base__status //
5149wuffs_base__pixel_buffer::set_color_u32_fill_rect(
5150 wuffs_base__rect_ie_u32 rect,
5151 wuffs_base__color_u32_argb_premul color) {
5152 return wuffs_base__pixel_buffer__set_color_u32_fill_rect(this, rect, color);
5153}
5154
5155#endif // __cplusplus
5156
5157// --------
5158
5159typedef struct wuffs_base__decode_frame_options__struct {
5160 // Do not access the private_impl's fields directly. There is no API/ABI
5161 // compatibility or safety guarantee if you do so.
5162 struct {
5163 uint8_t TODO;
5164 } private_impl;
5165
5166#ifdef __cplusplus
5167#endif // __cplusplus
5168
5169} wuffs_base__decode_frame_options;
5170
5171#ifdef __cplusplus
5172
5173#endif // __cplusplus
5174
5175// --------
5176
5177// wuffs_base__pixel_palette__closest_element returns the index of the palette
5178// element that minimizes the sum of squared differences of the four ARGB
5179// channels, working in premultiplied alpha. Ties favor the smaller index.
5180//
5181// The palette_slice.len may equal (N*4), for N less than 256, which means that
5182// only the first N palette elements are considered. It returns 0 when N is 0.
5183//
5184// Applying this function on a per-pixel basis will not produce whole-of-image
5185// dithering.
5186WUFFS_BASE__MAYBE_STATIC uint8_t //
5187wuffs_base__pixel_palette__closest_element(
5188 wuffs_base__slice_u8 palette_slice,
5189 wuffs_base__pixel_format palette_format,
5190 wuffs_base__color_u32_argb_premul c);
5191
5192// --------
5193
5194// TODO: should the func type take restrict pointers?
5195typedef uint64_t (*wuffs_base__pixel_swizzler__func)(uint8_t* dst_ptr,
5196 size_t dst_len,
5197 uint8_t* dst_palette_ptr,
5198 size_t dst_palette_len,
5199 const uint8_t* src_ptr,
5200 size_t src_len);
5201
5202typedef uint64_t (*wuffs_base__pixel_swizzler__transparent_black_func)(
5203 uint8_t* dst_ptr,
5204 size_t dst_len,
5205 uint8_t* dst_palette_ptr,
5206 size_t dst_palette_len,
5207 uint64_t num_pixels,
5208 uint32_t dst_pixfmt_bytes_per_pixel);
5209
5210typedef struct wuffs_base__pixel_swizzler__struct {
5211 // Do not access the private_impl's fields directly. There is no API/ABI
5212 // compatibility or safety guarantee if you do so.
5213 struct {
5214 wuffs_base__pixel_swizzler__func func;
5215 wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func;
5216 uint32_t dst_pixfmt_bytes_per_pixel;
5217 uint32_t src_pixfmt_bytes_per_pixel;
5218 } private_impl;
5219
5220#ifdef __cplusplus
5221 inline wuffs_base__status prepare(wuffs_base__pixel_format dst_pixfmt,
5222 wuffs_base__slice_u8 dst_palette,
5223 wuffs_base__pixel_format src_pixfmt,
5224 wuffs_base__slice_u8 src_palette,
5225 wuffs_base__pixel_blend blend);
5226 inline uint64_t swizzle_interleaved_from_slice(
5227 wuffs_base__slice_u8 dst,
5228 wuffs_base__slice_u8 dst_palette,
5229 wuffs_base__slice_u8 src) const;
5230#endif // __cplusplus
5231
5232} wuffs_base__pixel_swizzler;
5233
5234// wuffs_base__pixel_swizzler__prepare readies the pixel swizzler so that its
5235// other methods may be called.
5236//
5237// For modular builds that divide the base module into sub-modules, using this
5238// function requires the WUFFS_CONFIG__MODULE__BASE__PIXCONV sub-module, not
5239// just WUFFS_CONFIG__MODULE__BASE__CORE.
5240WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
5241wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
5242 wuffs_base__pixel_format dst_pixfmt,
5243 wuffs_base__slice_u8 dst_palette,
5244 wuffs_base__pixel_format src_pixfmt,
5245 wuffs_base__slice_u8 src_palette,
5246 wuffs_base__pixel_blend blend);
5247
5248// wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice converts pixels
5249// from a source format to a destination format.
5250//
5251// For modular builds that divide the base module into sub-modules, using this
5252// function requires the WUFFS_CONFIG__MODULE__BASE__PIXCONV sub-module, not
5253// just WUFFS_CONFIG__MODULE__BASE__CORE.
5254WUFFS_BASE__MAYBE_STATIC uint64_t //
5255wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
5256 const wuffs_base__pixel_swizzler* p,
5257 wuffs_base__slice_u8 dst,
5258 wuffs_base__slice_u8 dst_palette,
5259 wuffs_base__slice_u8 src);
5260
5261#ifdef __cplusplus
5262
5263inline wuffs_base__status //
5264wuffs_base__pixel_swizzler::prepare(wuffs_base__pixel_format dst_pixfmt,
5265 wuffs_base__slice_u8 dst_palette,
5266 wuffs_base__pixel_format src_pixfmt,
5267 wuffs_base__slice_u8 src_palette,
5268 wuffs_base__pixel_blend blend) {
5269 return wuffs_base__pixel_swizzler__prepare(this, dst_pixfmt, dst_palette,
5270 src_pixfmt, src_palette, blend);
5271}
5272
5273uint64_t //
5274wuffs_base__pixel_swizzler::swizzle_interleaved_from_slice(
5275 wuffs_base__slice_u8 dst,
5276 wuffs_base__slice_u8 dst_palette,
5277 wuffs_base__slice_u8 src) const {
5278 return wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
5279 this, dst, dst_palette, src);
5280}
5281
5282#endif // __cplusplus
5283
5284// ---------------- String Conversions
5285
5286// Options (bitwise or'ed together) for wuffs_base__parse_number_xxx
5287// functions. The XXX options apply to both integer and floating point. The FXX
5288// options apply only to floating point.
5289
5290#define WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5291
5292// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES means to accept
5293// inputs like "00", "0644" and "00.7". By default, they are rejected.
5294#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES \
5295 ((uint32_t)0x00000001)
5296
5297// WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES means to accept inputs like
5298// "1__2" and "_3.141_592". By default, they are rejected.
5299#define WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES ((uint32_t)0x00000002)
5300
5301// WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to accept
5302// "1,5" and not "1.5" as one-and-a-half.
5303//
5304// If the caller wants to accept either, it is responsible for canonicalizing
5305// the input before calling wuffs_base__parse_number_fxx. The caller also has
5306// more context on e.g. exactly how to treat something like "$1,234".
5307#define WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
5308 ((uint32_t)0x00000010)
5309
5310// WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN means to reject inputs that
5311// would lead to infinite or Not-a-Number floating point values. By default,
5312// they are accepted.
5313//
5314// This affects the literal "inf" as input, but also affects inputs like
5315// "1e999" that would overflow double-precision floating point.
5316#define WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN ((uint32_t)0x00000020)
5317
5318// --------
5319
5320// Options (bitwise or'ed together) for wuffs_base__render_number_xxx
5321// functions. The XXX options apply to both integer and floating point. The FXX
5322// options apply only to floating point.
5323
5324#define WUFFS_BASE__RENDER_NUMBER_XXX__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5325
5326// WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT means to render to the right side
5327// (higher indexes) of the destination slice, leaving any untouched bytes on
5328// the left side (lower indexes). The default is vice versa: rendering on the
5329// left with slack on the right.
5330#define WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT ((uint32_t)0x00000100)
5331
5332// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN means to render the leading
5333// "+" for non-negative numbers: "+0" and "+12.3" instead of "0" and "12.3".
5334#define WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN ((uint32_t)0x00000200)
5335
5336// WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA means to render
5337// one-and-a-half as "1,5" instead of "1.5".
5338#define WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA \
5339 ((uint32_t)0x00001000)
5340
5341// WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ETC means whether to never
5342// (EXPONENT_ABSENT, equivalent to printf's "%f") or to always
5343// (EXPONENT_PRESENT, equivalent to printf's "%e") render a floating point
5344// number as "1.23e+05" instead of "123000".
5345//
5346// Having both bits set is the same has having neither bit set, where the
5347// notation used depends on whether the exponent is sufficiently large: "0.5"
5348// is preferred over "5e-01" but "5e-09" is preferred over "0.000000005".
5349#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT ((uint32_t)0x00002000)
5350#define WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT ((uint32_t)0x00004000)
5351
5352// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION means to render the
5353// smallest number of digits so that parsing the resultant string will recover
5354// the same double-precision floating point number.
5355//
5356// For example, double-precision cannot distinguish between 0.3 and
5357// 0.299999999999999988897769753748434595763683319091796875, so when this bit
5358// is set, rendering the latter will produce "0.3" but rendering
5359// 0.3000000000000000444089209850062616169452667236328125 will produce
5360// "0.30000000000000004".
5361#define WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION \
5362 ((uint32_t)0x00008000)
5363
5364// ---------------- IEEE 754 Floating Point
5365
5366// wuffs_base__ieee_754_bit_representation__etc converts between a double
5367// precision numerical value and its IEEE 754 representations:
Nigel Taobf9dab32021-11-18 19:19:55 +11005368// - 16-bit: 1 sign bit, 5 exponent bits, 10 explicit significand bits.
5369// - 32-bit: 1 sign bit, 8 exponent bits, 23 explicit significand bits.
5370// - 64-bit: 1 sign bit, 11 exponent bits, 52 explicit significand bits.
Nigel Taoe360a532021-04-05 22:47:03 +10005371//
5372// For example, it converts between:
5373// - +1.0 and 0x3C00, 0x3F80_0000 or 0x3FF0_0000_0000_0000.
5374// - +5.5 and 0x4580, 0x40B0_0000 or 0x4016_0000_0000_0000.
5375// - -inf and 0xFC00, 0xFF80_0000 or 0xFFF0_0000_0000_0000.
5376//
5377// Converting from f64 to shorter formats (f16 or f32, represented in C as
5378// uint16_t and uint32_t) may be lossy. Such functions have names that look
5379// like etc_truncate, as converting finite numbers produce equal or smaller
5380// (closer-to-zero) finite numbers. For example, 1048576.0 is a perfectly valid
5381// f64 number, but converting it to a f16 (with truncation) produces 65504.0,
5382// the largest finite f16 number. Truncating a f64-typed value d to f32 does
5383// not always produce the same result as the C-style cast ((float)d), as
5384// casting can convert from finite numbers to infinite ones.
5385//
5386// Converting infinities or NaNs produces infinities or NaNs and always report
5387// no loss, even though there a multiple NaN representations so that round-
5388// tripping a f64-typed NaN may produce a different 64 bits. Nonetheless, the
5389// etc_truncate functions preserve a NaN's "quiet vs signaling" bit.
5390//
5391// See https://en.wikipedia.org/wiki/Double-precision_floating-point_format
5392
5393typedef struct wuffs_base__lossy_value_u16__struct {
5394 uint16_t value;
5395 bool lossy;
5396} wuffs_base__lossy_value_u16;
5397
5398typedef struct wuffs_base__lossy_value_u32__struct {
5399 uint32_t value;
5400 bool lossy;
5401} wuffs_base__lossy_value_u32;
5402
5403WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 //
5404wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f);
5405
5406WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 //
5407wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f);
5408
5409static inline uint64_t //
5410wuffs_base__ieee_754_bit_representation__from_f64_to_u64(double f) {
5411 uint64_t u = 0;
5412 if (sizeof(uint64_t) == sizeof(double)) {
5413 memcpy(&u, &f, sizeof(uint64_t));
5414 }
5415 return u;
5416}
5417
5418static inline double //
5419wuffs_base__ieee_754_bit_representation__from_u16_to_f64(uint16_t u) {
5420 uint64_t v = ((uint64_t)(u & 0x8000)) << 48;
5421
5422 do {
5423 uint64_t exp = (u >> 10) & 0x1F;
5424 uint64_t man = u & 0x3FF;
5425 if (exp == 0x1F) { // Infinity or NaN.
5426 exp = 2047;
5427 } else if (exp != 0) { // Normal.
5428 exp += 1008; // 1008 = 1023 - 15, the difference in biases.
5429 } else if (man != 0) { // Subnormal but non-zero.
5430 uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
5431 exp = 1062 - clz; // 1062 = 1008 + 64 - 10.
5432 man = 0x3FF & (man << (clz - 53));
5433 } else { // Zero.
5434 break;
5435 }
5436 v |= (exp << 52) | (man << 42);
5437 } while (0);
5438
5439 double f = 0;
5440 if (sizeof(uint64_t) == sizeof(double)) {
5441 memcpy(&f, &v, sizeof(uint64_t));
5442 }
5443 return f;
5444}
5445
5446static inline double //
5447wuffs_base__ieee_754_bit_representation__from_u32_to_f64(uint32_t u) {
5448 float f = 0;
5449 if (sizeof(uint32_t) == sizeof(float)) {
5450 memcpy(&f, &u, sizeof(uint32_t));
5451 }
5452 return (double)f;
5453}
5454
5455static inline double //
5456wuffs_base__ieee_754_bit_representation__from_u64_to_f64(uint64_t u) {
5457 double f = 0;
5458 if (sizeof(uint64_t) == sizeof(double)) {
5459 memcpy(&f, &u, sizeof(uint64_t));
5460 }
5461 return f;
5462}
5463
5464// ---------------- Parsing and Rendering Numbers
5465
5466// wuffs_base__parse_number_f64 parses the floating point number in s. For
5467// example, if s contains the bytes "1.5" then it will return the double 1.5.
5468//
5469// It returns an error if s does not contain a floating point number.
5470//
5471// It does not necessarily return an error if the conversion is lossy, e.g. if
5472// s is "0.3", which double-precision floating point cannot represent exactly.
5473//
5474// Similarly, the returned value may be infinite (and no error returned) even
5475// if s was not "inf", when the input is nominally finite but sufficiently
5476// larger than DBL_MAX, about 1.8e+308.
5477//
5478// It is similar to the C standard library's strtod function, but:
5479// - Errors are returned in-band (in a result type), not out-of-band (errno).
5480// - It takes a slice (a pointer and length), not a NUL-terminated C string.
5481// - It does not take an optional endptr argument. It does not allow a partial
5482// parse: it returns an error unless all of s is consumed.
5483// - It does not allow whitespace, leading or otherwise.
5484// - It does not allow hexadecimal floating point numbers.
5485// - It is not affected by i18n / l10n settings such as environment variables.
5486//
5487// The options argument can change these, but by default, it:
5488// - Allows "inf", "+Infinity" and "-NAN", case insensitive. Similarly,
5489// without an explicit opt-out, it would successfully parse "1e999" as
5490// infinity, even though it overflows double-precision floating point.
5491// - Rejects underscores. With an explicit opt-in, "_3.141_592" would
5492// successfully parse as an approximation to π.
5493// - Rejects unnecessary leading zeroes: "00", "0644" and "00.7".
5494// - Uses a dot '1.5' instead of a comma '1,5' for the decimal separator.
5495//
5496// For modular builds that divide the base module into sub-modules, using this
5497// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
5498// just WUFFS_CONFIG__MODULE__BASE__CORE.
5499WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
5500wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options);
5501
5502// wuffs_base__parse_number_i64 parses the ASCII integer in s. For example, if
5503// s contains the bytes "-123" then it will return the int64_t -123.
5504//
5505// It returns an error if s does not contain an integer or if the integer
5506// within would overflow an int64_t.
5507//
5508// It is similar to wuffs_base__parse_number_u64 but it returns a signed
5509// integer, not an unsigned integer. It also allows a leading '+' or '-'.
5510//
5511// For modular builds that divide the base module into sub-modules, using this
5512// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5513// just WUFFS_CONFIG__MODULE__BASE__CORE.
5514WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 //
5515wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options);
5516
5517// wuffs_base__parse_number_u64 parses the ASCII integer in s. For example, if
5518// s contains the bytes "123" then it will return the uint64_t 123.
5519//
5520// It returns an error if s does not contain an integer or if the integer
5521// within would overflow a uint64_t.
5522//
5523// It is similar to the C standard library's strtoull function, but:
5524// - Errors are returned in-band (in a result type), not out-of-band (errno).
5525// - It takes a slice (a pointer and length), not a NUL-terminated C string.
5526// - It does not take an optional endptr argument. It does not allow a partial
5527// parse: it returns an error unless all of s is consumed.
5528// - It does not allow whitespace, leading or otherwise.
5529// - It does not allow a leading '+' or '-'.
5530// - It does not take a base argument (e.g. base 10 vs base 16). Instead, it
5531// always accepts both decimal (e.g "1234", "0d5678") and hexadecimal (e.g.
5532// "0x9aBC"). The caller is responsible for prior filtering of e.g. hex
5533// numbers if they are unwanted. For example, Wuffs' JSON decoder will only
5534// produce a wuffs_base__token for decimal numbers, not hexadecimal.
5535// - It is not affected by i18n / l10n settings such as environment variables.
5536//
5537// The options argument can change these, but by default, it:
5538// - Rejects underscores. With an explicit opt-in, "__0D_1_002" would
5539// successfully parse as "one thousand and two". Underscores are still
5540// rejected inside the optional 2-byte opening "0d" or "0X" that denotes
5541// base-10 or base-16.
5542// - Rejects unnecessary leading zeroes: "00" and "0644".
5543//
5544// For modular builds that divide the base module into sub-modules, using this
5545// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5546// just WUFFS_CONFIG__MODULE__BASE__CORE.
5547WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 //
5548wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options);
5549
5550// --------
5551
5552// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL is the string length of
5553// "-9223372036854775808" and "+9223372036854775807", INT64_MIN and INT64_MAX.
5554#define WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL 20
5555
5556// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL is the string length of
5557// "+18446744073709551615", UINT64_MAX.
5558#define WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL 21
5559
5560// wuffs_base__render_number_f64 writes the decimal encoding of x to dst and
5561// returns the number of bytes written. If dst is shorter than the entire
5562// encoding, it returns 0 (and no bytes are written).
5563//
5564// For those familiar with C's printf or Go's fmt.Printf functions:
5565// - "%e" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT option.
5566// - "%f" means the WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT option.
5567// - "%g" means neither or both bits are set.
5568//
5569// The precision argument controls the number of digits rendered, excluding the
5570// exponent (the "e+05" in "1.23e+05"):
5571// - for "%e" and "%f" it is the number of digits after the decimal separator,
5572// - for "%g" it is the number of significant digits (and trailing zeroes are
5573// removed).
5574//
5575// A precision of 6 gives similar output to printf's defaults.
5576//
5577// A precision greater than 4095 is equivalent to 4095.
5578//
5579// The precision argument is ignored when the
5580// WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION option is set. This is
5581// similar to Go's strconv.FormatFloat with a negative (i.e. non-sensical)
5582// precision, but there is no corresponding feature in C's printf.
5583//
5584// Extreme values of x will be rendered as "NaN", "Inf" (or "+Inf" if the
5585// WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN option is set) or "-Inf".
5586//
5587// For modular builds that divide the base module into sub-modules, using this
5588// function requires the WUFFS_CONFIG__MODULE__BASE__FLOATCONV sub-module, not
5589// just WUFFS_CONFIG__MODULE__BASE__CORE.
5590WUFFS_BASE__MAYBE_STATIC size_t //
5591wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
5592 double x,
5593 uint32_t precision,
5594 uint32_t options);
5595
5596// wuffs_base__render_number_i64 writes the decimal encoding of x to dst and
5597// returns the number of bytes written. If dst is shorter than the entire
5598// encoding, it returns 0 (and no bytes are written).
5599//
5600// dst will never be too short if its length is at least 20, also known as
5601// WUFFS_BASE__I64__BYTE_LENGTH__MAX_INCL.
5602//
5603// For modular builds that divide the base module into sub-modules, using this
5604// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5605// just WUFFS_CONFIG__MODULE__BASE__CORE.
5606WUFFS_BASE__MAYBE_STATIC size_t //
5607wuffs_base__render_number_i64(wuffs_base__slice_u8 dst,
5608 int64_t x,
5609 uint32_t options);
5610
5611// wuffs_base__render_number_u64 writes the decimal encoding of x to dst and
5612// returns the number of bytes written. If dst is shorter than the entire
5613// encoding, it returns 0 (and no bytes are written).
5614//
5615// dst will never be too short if its length is at least 21, also known as
5616// WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL.
5617//
5618// For modular builds that divide the base module into sub-modules, using this
5619// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5620// just WUFFS_CONFIG__MODULE__BASE__CORE.
5621WUFFS_BASE__MAYBE_STATIC size_t //
5622wuffs_base__render_number_u64(wuffs_base__slice_u8 dst,
5623 uint64_t x,
5624 uint32_t options);
5625
5626// ---------------- Base-16
5627
5628// Options (bitwise or'ed together) for wuffs_base__base_16__xxx functions.
5629
5630#define WUFFS_BASE__BASE_16__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5631
5632// wuffs_base__base_16__decode2 converts "6A6b" to "jk", where e.g. 'j' is
5633// U+006A. There are 2 src bytes for every dst byte.
5634//
5635// It assumes that the src bytes are two hexadecimal digits (0-9, A-F, a-f),
5636// repeated. It may write nonsense bytes if not, although it will not read or
5637// write out of bounds.
5638//
5639// For modular builds that divide the base module into sub-modules, using this
5640// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5641// just WUFFS_CONFIG__MODULE__BASE__CORE.
5642WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5643wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
5644 wuffs_base__slice_u8 src,
5645 bool src_closed,
5646 uint32_t options);
5647
5648// wuffs_base__base_16__decode4 converts both "\\x6A\\x6b" and "??6a??6B" to
5649// "jk", where e.g. 'j' is U+006A. There are 4 src bytes for every dst byte.
5650//
5651// It assumes that the src bytes are two ignored bytes and then two hexadecimal
5652// digits (0-9, A-F, a-f), repeated. It may write nonsense bytes if not,
5653// although it will not read or write out of bounds.
5654//
5655// For modular builds that divide the base module into sub-modules, using this
5656// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5657// just WUFFS_CONFIG__MODULE__BASE__CORE.
5658WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5659wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
5660 wuffs_base__slice_u8 src,
5661 bool src_closed,
5662 uint32_t options);
5663
5664// wuffs_base__base_16__encode2 converts "jk" to "6A6B", where e.g. 'j' is
5665// U+006A. There are 2 dst bytes for every src byte.
5666//
5667// For modular builds that divide the base module into sub-modules, using this
5668// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5669// just WUFFS_CONFIG__MODULE__BASE__CORE.
5670WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5671wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
5672 wuffs_base__slice_u8 src,
5673 bool src_closed,
5674 uint32_t options);
5675
5676// wuffs_base__base_16__encode4 converts "jk" to "\\x6A\\x6B", where e.g. 'j'
5677// is U+006A. There are 4 dst bytes for every src byte.
5678//
5679// For modular builds that divide the base module into sub-modules, using this
5680// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5681// just WUFFS_CONFIG__MODULE__BASE__CORE.
5682WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5683wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
5684 wuffs_base__slice_u8 src,
5685 bool src_closed,
5686 uint32_t options);
5687
5688// ---------------- Base-64
5689
5690// Options (bitwise or'ed together) for wuffs_base__base_64__xxx functions.
5691
5692#define WUFFS_BASE__BASE_64__DEFAULT_OPTIONS ((uint32_t)0x00000000)
5693
5694// WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING means that, when decoding base-64,
5695// the input may (but does not need to) be padded with '=' bytes so that the
5696// overall encoded length in bytes is a multiple of 4. A successful decoding
5697// will return a num_src that includes those padding bytes.
5698//
5699// Excess padding (e.g. three final '='s) will be rejected as bad data.
5700#define WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING ((uint32_t)0x00000001)
5701
5702// WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING means that, when encoding base-64,
5703// the output will be padded with '=' bytes so that the overall encoded length
5704// in bytes is a multiple of 4.
5705#define WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING ((uint32_t)0x00000002)
5706
5707// WUFFS_BASE__BASE_64__URL_ALPHABET means that, for base-64, the URL-friendly
5708// and file-name-friendly alphabet be used, as per RFC 4648 section 5. When
5709// this option bit is off, the standard alphabet from section 4 is used.
5710#define WUFFS_BASE__BASE_64__URL_ALPHABET ((uint32_t)0x00000100)
5711
5712// wuffs_base__base_64__decode transforms base-64 encoded bytes from src to
5713// arbitrary bytes in dst.
5714//
5715// It will not permit line breaks or other whitespace in src. Filtering those
5716// out is the responsibility of the caller.
5717//
5718// For modular builds that divide the base module into sub-modules, using this
5719// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5720// just WUFFS_CONFIG__MODULE__BASE__CORE.
5721WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5722wuffs_base__base_64__decode(wuffs_base__slice_u8 dst,
5723 wuffs_base__slice_u8 src,
5724 bool src_closed,
5725 uint32_t options);
5726
5727// wuffs_base__base_64__encode transforms arbitrary bytes from src to base-64
5728// encoded bytes in dst.
5729//
5730// For modular builds that divide the base module into sub-modules, using this
5731// function requires the WUFFS_CONFIG__MODULE__BASE__INTCONV sub-module, not
5732// just WUFFS_CONFIG__MODULE__BASE__CORE.
5733WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
5734wuffs_base__base_64__encode(wuffs_base__slice_u8 dst,
5735 wuffs_base__slice_u8 src,
5736 bool src_closed,
5737 uint32_t options);
5738
5739// ---------------- Unicode and UTF-8
5740
5741#define WUFFS_BASE__UNICODE_CODE_POINT__MIN_INCL 0x00000000
5742#define WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL 0x0010FFFF
5743
5744#define WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER 0x0000FFFD
5745
5746#define WUFFS_BASE__UNICODE_SURROGATE__MIN_INCL 0x0000D800
5747#define WUFFS_BASE__UNICODE_SURROGATE__MAX_INCL 0x0000DFFF
5748
5749#define WUFFS_BASE__ASCII__MIN_INCL 0x00
5750#define WUFFS_BASE__ASCII__MAX_INCL 0x7F
5751
5752#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MIN_INCL 1
5753#define WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL 4
5754
5755#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MIN_INCL 0x00000000
5756#define WUFFS_BASE__UTF_8__BYTE_LENGTH_1__CODE_POINT__MAX_INCL 0x0000007F
5757#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MIN_INCL 0x00000080
5758#define WUFFS_BASE__UTF_8__BYTE_LENGTH_2__CODE_POINT__MAX_INCL 0x000007FF
5759#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MIN_INCL 0x00000800
5760#define WUFFS_BASE__UTF_8__BYTE_LENGTH_3__CODE_POINT__MAX_INCL 0x0000FFFF
5761#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MIN_INCL 0x00010000
5762#define WUFFS_BASE__UTF_8__BYTE_LENGTH_4__CODE_POINT__MAX_INCL 0x0010FFFF
5763
5764// --------
5765
5766// wuffs_base__utf_8__next__output is the type returned by
5767// wuffs_base__utf_8__next.
5768typedef struct wuffs_base__utf_8__next__output__struct {
5769 uint32_t code_point;
5770 uint32_t byte_length;
5771
5772#ifdef __cplusplus
5773 inline bool is_valid() const;
5774#endif // __cplusplus
5775
5776} wuffs_base__utf_8__next__output;
5777
5778static inline wuffs_base__utf_8__next__output //
5779wuffs_base__make_utf_8__next__output(uint32_t code_point,
5780 uint32_t byte_length) {
5781 wuffs_base__utf_8__next__output ret;
5782 ret.code_point = code_point;
5783 ret.byte_length = byte_length;
5784 return ret;
5785}
5786
5787static inline bool //
5788wuffs_base__utf_8__next__output__is_valid(
5789 const wuffs_base__utf_8__next__output* o) {
5790 if (o) {
5791 uint32_t cp = o->code_point;
5792 switch (o->byte_length) {
5793 case 1:
5794 return (cp <= 0x7F);
5795 case 2:
5796 return (0x080 <= cp) && (cp <= 0x7FF);
5797 case 3:
5798 // Avoid the 0xD800 ..= 0xDFFF surrogate range.
5799 return ((0x0800 <= cp) && (cp <= 0xD7FF)) ||
5800 ((0xE000 <= cp) && (cp <= 0xFFFF));
5801 case 4:
5802 return (0x00010000 <= cp) && (cp <= 0x0010FFFF);
5803 }
5804 }
5805 return false;
5806}
5807
5808#ifdef __cplusplus
5809
5810inline bool //
5811wuffs_base__utf_8__next__output::is_valid() const {
5812 return wuffs_base__utf_8__next__output__is_valid(this);
5813}
5814
5815#endif // __cplusplus
5816
5817// --------
5818
5819// wuffs_base__utf_8__encode writes the UTF-8 encoding of code_point to s and
5820// returns the number of bytes written. If code_point is invalid, or if s is
5821// shorter than the entire encoding, it returns 0 (and no bytes are written).
5822//
5823// s will never be too short if its length is at least 4, also known as
5824// WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL.
5825//
5826// For modular builds that divide the base module into sub-modules, using this
5827// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5828// WUFFS_CONFIG__MODULE__BASE__CORE.
5829WUFFS_BASE__MAYBE_STATIC size_t //
5830wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point);
5831
5832// wuffs_base__utf_8__next returns the next UTF-8 code point (and that code
5833// point's byte length) at the start of the read-only slice (s_ptr, s_len).
5834//
5835// There are exactly two cases in which this function returns something where
5836// wuffs_base__utf_8__next__output__is_valid is false:
5837// - If s is empty then it returns {.code_point=0, .byte_length=0}.
5838// - If s is non-empty and starts with invalid UTF-8 then it returns
5839// {.code_point=WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, .byte_length=1}.
5840//
5841// Otherwise, it returns something where
5842// wuffs_base__utf_8__next__output__is_valid is true.
5843//
5844// In any case, it always returns an output that satisfies both of:
5845// - (output.code_point <= WUFFS_BASE__UNICODE_CODE_POINT__MAX_INCL).
5846// - (output.byte_length <= s_len).
5847//
5848// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
5849// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
5850// code point, then this function may return something invalid. It is the
5851// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
5852//
5853// For modular builds that divide the base module into sub-modules, using this
5854// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5855// WUFFS_CONFIG__MODULE__BASE__CORE.
5856WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
5857wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len);
5858
5859// wuffs_base__utf_8__next_from_end is like wuffs_base__utf_8__next except that
5860// it looks at the end of (s_ptr, s_len) instead of the start.
5861//
5862// For modular builds that divide the base module into sub-modules, using this
5863// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5864// WUFFS_CONFIG__MODULE__BASE__CORE.
5865WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
5866wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len);
5867
5868// wuffs_base__utf_8__longest_valid_prefix returns the largest n such that the
5869// sub-slice s[..n] is valid UTF-8, where s is the read-only slice (s_ptr,
5870// s_len).
5871//
5872// In particular, it returns s_len if and only if all of s is valid UTF-8.
5873//
5874// If s is a sub-slice of a larger slice of valid UTF-8, but that sub-slice
5875// boundary occurs in the middle of a multi-byte UTF-8 encoding of a single
5876// code point, then this function will return less than s_len. It is the
5877// caller's responsibility to split on or otherwise manage UTF-8 boundaries.
5878//
5879// For modular builds that divide the base module into sub-modules, using this
5880// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5881// WUFFS_CONFIG__MODULE__BASE__CORE.
5882WUFFS_BASE__MAYBE_STATIC size_t //
5883wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
5884
5885// wuffs_base__ascii__longest_valid_prefix returns the largest n such that the
5886// sub-slice s[..n] is valid ASCII, where s is the read-only slice (s_ptr,
5887// s_len).
5888//
5889// In particular, it returns s_len if and only if all of s is valid ASCII.
5890// Equivalently, when none of the bytes in s have the 0x80 high bit set.
5891//
5892// For modular builds that divide the base module into sub-modules, using this
5893// function requires the WUFFS_CONFIG__MODULE__BASE__UTF8 sub-module, not just
5894// WUFFS_CONFIG__MODULE__BASE__CORE.
5895WUFFS_BASE__MAYBE_STATIC size_t //
5896wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len);
5897
5898// ---------------- Interface Declarations.
5899
5900// For modular builds that divide the base module into sub-modules, using these
5901// functions require the WUFFS_CONFIG__MODULE__BASE__INTERFACES sub-module, not
5902// just WUFFS_CONFIG__MODULE__BASE__CORE.
5903
5904// --------
5905
5906extern const char wuffs_base__hasher_u32__vtable_name[];
5907
5908typedef struct wuffs_base__hasher_u32__func_ptrs__struct {
5909 wuffs_base__empty_struct (*set_quirk_enabled)(
5910 void* self,
5911 uint32_t a_quirk,
5912 bool a_enabled);
5913 uint32_t (*update_u32)(
5914 void* self,
5915 wuffs_base__slice_u8 a_x);
5916} wuffs_base__hasher_u32__func_ptrs;
5917
5918typedef struct wuffs_base__hasher_u32__struct wuffs_base__hasher_u32;
5919
5920WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
5921wuffs_base__hasher_u32__set_quirk_enabled(
5922 wuffs_base__hasher_u32* self,
5923 uint32_t a_quirk,
5924 bool a_enabled);
5925
5926WUFFS_BASE__MAYBE_STATIC uint32_t
5927wuffs_base__hasher_u32__update_u32(
5928 wuffs_base__hasher_u32* self,
5929 wuffs_base__slice_u8 a_x);
5930
5931#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
5932
5933struct wuffs_base__hasher_u32__struct {
5934 struct {
5935 uint32_t magic;
5936 uint32_t active_coroutine;
5937 wuffs_base__vtable first_vtable;
5938 } private_impl;
5939
5940#ifdef __cplusplus
5941#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
5942 using unique_ptr = std::unique_ptr<wuffs_base__hasher_u32, decltype(&free)>;
5943#endif
5944
5945 inline wuffs_base__empty_struct
5946 set_quirk_enabled(
5947 uint32_t a_quirk,
5948 bool a_enabled) {
5949 return wuffs_base__hasher_u32__set_quirk_enabled(
5950 this, a_quirk, a_enabled);
5951 }
5952
5953 inline uint32_t
5954 update_u32(
5955 wuffs_base__slice_u8 a_x) {
5956 return wuffs_base__hasher_u32__update_u32(
5957 this, a_x);
5958 }
5959
5960#endif // __cplusplus
5961}; // struct wuffs_base__hasher_u32__struct
5962
5963#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
5964
5965// --------
5966
5967extern const char wuffs_base__image_decoder__vtable_name[];
5968
5969typedef struct wuffs_base__image_decoder__func_ptrs__struct {
5970 wuffs_base__status (*decode_frame)(
5971 void* self,
5972 wuffs_base__pixel_buffer* a_dst,
5973 wuffs_base__io_buffer* a_src,
5974 wuffs_base__pixel_blend a_blend,
5975 wuffs_base__slice_u8 a_workbuf,
5976 wuffs_base__decode_frame_options* a_opts);
5977 wuffs_base__status (*decode_frame_config)(
5978 void* self,
5979 wuffs_base__frame_config* a_dst,
5980 wuffs_base__io_buffer* a_src);
5981 wuffs_base__status (*decode_image_config)(
5982 void* self,
5983 wuffs_base__image_config* a_dst,
5984 wuffs_base__io_buffer* a_src);
5985 wuffs_base__rect_ie_u32 (*frame_dirty_rect)(
5986 const void* self);
5987 uint32_t (*num_animation_loops)(
5988 const void* self);
5989 uint64_t (*num_decoded_frame_configs)(
5990 const void* self);
5991 uint64_t (*num_decoded_frames)(
5992 const void* self);
5993 wuffs_base__status (*restart_frame)(
5994 void* self,
5995 uint64_t a_index,
5996 uint64_t a_io_position);
5997 wuffs_base__empty_struct (*set_quirk_enabled)(
5998 void* self,
5999 uint32_t a_quirk,
6000 bool a_enabled);
6001 wuffs_base__empty_struct (*set_report_metadata)(
6002 void* self,
6003 uint32_t a_fourcc,
6004 bool a_report);
6005 wuffs_base__status (*tell_me_more)(
6006 void* self,
6007 wuffs_base__io_buffer* a_dst,
6008 wuffs_base__more_information* a_minfo,
6009 wuffs_base__io_buffer* a_src);
6010 wuffs_base__range_ii_u64 (*workbuf_len)(
6011 const void* self);
6012} wuffs_base__image_decoder__func_ptrs;
6013
6014typedef struct wuffs_base__image_decoder__struct wuffs_base__image_decoder;
6015
6016WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6017wuffs_base__image_decoder__decode_frame(
6018 wuffs_base__image_decoder* self,
6019 wuffs_base__pixel_buffer* a_dst,
6020 wuffs_base__io_buffer* a_src,
6021 wuffs_base__pixel_blend a_blend,
6022 wuffs_base__slice_u8 a_workbuf,
6023 wuffs_base__decode_frame_options* a_opts);
6024
6025WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6026wuffs_base__image_decoder__decode_frame_config(
6027 wuffs_base__image_decoder* self,
6028 wuffs_base__frame_config* a_dst,
6029 wuffs_base__io_buffer* a_src);
6030
6031WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6032wuffs_base__image_decoder__decode_image_config(
6033 wuffs_base__image_decoder* self,
6034 wuffs_base__image_config* a_dst,
6035 wuffs_base__io_buffer* a_src);
6036
6037WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
6038wuffs_base__image_decoder__frame_dirty_rect(
6039 const wuffs_base__image_decoder* self);
6040
6041WUFFS_BASE__MAYBE_STATIC uint32_t
6042wuffs_base__image_decoder__num_animation_loops(
6043 const wuffs_base__image_decoder* self);
6044
6045WUFFS_BASE__MAYBE_STATIC uint64_t
6046wuffs_base__image_decoder__num_decoded_frame_configs(
6047 const wuffs_base__image_decoder* self);
6048
6049WUFFS_BASE__MAYBE_STATIC uint64_t
6050wuffs_base__image_decoder__num_decoded_frames(
6051 const wuffs_base__image_decoder* self);
6052
6053WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6054wuffs_base__image_decoder__restart_frame(
6055 wuffs_base__image_decoder* self,
6056 uint64_t a_index,
6057 uint64_t a_io_position);
6058
6059WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6060wuffs_base__image_decoder__set_quirk_enabled(
6061 wuffs_base__image_decoder* self,
6062 uint32_t a_quirk,
6063 bool a_enabled);
6064
6065WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6066wuffs_base__image_decoder__set_report_metadata(
6067 wuffs_base__image_decoder* self,
6068 uint32_t a_fourcc,
6069 bool a_report);
6070
6071WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6072wuffs_base__image_decoder__tell_me_more(
6073 wuffs_base__image_decoder* self,
6074 wuffs_base__io_buffer* a_dst,
6075 wuffs_base__more_information* a_minfo,
6076 wuffs_base__io_buffer* a_src);
6077
6078WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6079wuffs_base__image_decoder__workbuf_len(
6080 const wuffs_base__image_decoder* self);
6081
6082#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6083
6084struct wuffs_base__image_decoder__struct {
6085 struct {
6086 uint32_t magic;
6087 uint32_t active_coroutine;
6088 wuffs_base__vtable first_vtable;
6089 } private_impl;
6090
6091#ifdef __cplusplus
6092#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6093 using unique_ptr = std::unique_ptr<wuffs_base__image_decoder, decltype(&free)>;
6094#endif
6095
6096 inline wuffs_base__status
6097 decode_frame(
6098 wuffs_base__pixel_buffer* a_dst,
6099 wuffs_base__io_buffer* a_src,
6100 wuffs_base__pixel_blend a_blend,
6101 wuffs_base__slice_u8 a_workbuf,
6102 wuffs_base__decode_frame_options* a_opts) {
6103 return wuffs_base__image_decoder__decode_frame(
6104 this, a_dst, a_src, a_blend, a_workbuf, a_opts);
6105 }
6106
6107 inline wuffs_base__status
6108 decode_frame_config(
6109 wuffs_base__frame_config* a_dst,
6110 wuffs_base__io_buffer* a_src) {
6111 return wuffs_base__image_decoder__decode_frame_config(
6112 this, a_dst, a_src);
6113 }
6114
6115 inline wuffs_base__status
6116 decode_image_config(
6117 wuffs_base__image_config* a_dst,
6118 wuffs_base__io_buffer* a_src) {
6119 return wuffs_base__image_decoder__decode_image_config(
6120 this, a_dst, a_src);
6121 }
6122
6123 inline wuffs_base__rect_ie_u32
6124 frame_dirty_rect() const {
6125 return wuffs_base__image_decoder__frame_dirty_rect(this);
6126 }
6127
6128 inline uint32_t
6129 num_animation_loops() const {
6130 return wuffs_base__image_decoder__num_animation_loops(this);
6131 }
6132
6133 inline uint64_t
6134 num_decoded_frame_configs() const {
6135 return wuffs_base__image_decoder__num_decoded_frame_configs(this);
6136 }
6137
6138 inline uint64_t
6139 num_decoded_frames() const {
6140 return wuffs_base__image_decoder__num_decoded_frames(this);
6141 }
6142
6143 inline wuffs_base__status
6144 restart_frame(
6145 uint64_t a_index,
6146 uint64_t a_io_position) {
6147 return wuffs_base__image_decoder__restart_frame(
6148 this, a_index, a_io_position);
6149 }
6150
6151 inline wuffs_base__empty_struct
6152 set_quirk_enabled(
6153 uint32_t a_quirk,
6154 bool a_enabled) {
6155 return wuffs_base__image_decoder__set_quirk_enabled(
6156 this, a_quirk, a_enabled);
6157 }
6158
6159 inline wuffs_base__empty_struct
6160 set_report_metadata(
6161 uint32_t a_fourcc,
6162 bool a_report) {
6163 return wuffs_base__image_decoder__set_report_metadata(
6164 this, a_fourcc, a_report);
6165 }
6166
6167 inline wuffs_base__status
6168 tell_me_more(
6169 wuffs_base__io_buffer* a_dst,
6170 wuffs_base__more_information* a_minfo,
6171 wuffs_base__io_buffer* a_src) {
6172 return wuffs_base__image_decoder__tell_me_more(
6173 this, a_dst, a_minfo, a_src);
6174 }
6175
6176 inline wuffs_base__range_ii_u64
6177 workbuf_len() const {
6178 return wuffs_base__image_decoder__workbuf_len(this);
6179 }
6180
6181#endif // __cplusplus
6182}; // struct wuffs_base__image_decoder__struct
6183
6184#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6185
6186// --------
6187
6188extern const char wuffs_base__io_transformer__vtable_name[];
6189
6190typedef struct wuffs_base__io_transformer__func_ptrs__struct {
6191 wuffs_base__empty_struct (*set_quirk_enabled)(
6192 void* self,
6193 uint32_t a_quirk,
6194 bool a_enabled);
6195 wuffs_base__status (*transform_io)(
6196 void* self,
6197 wuffs_base__io_buffer* a_dst,
6198 wuffs_base__io_buffer* a_src,
6199 wuffs_base__slice_u8 a_workbuf);
6200 wuffs_base__range_ii_u64 (*workbuf_len)(
6201 const void* self);
6202} wuffs_base__io_transformer__func_ptrs;
6203
6204typedef struct wuffs_base__io_transformer__struct wuffs_base__io_transformer;
6205
6206WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6207wuffs_base__io_transformer__set_quirk_enabled(
6208 wuffs_base__io_transformer* self,
6209 uint32_t a_quirk,
6210 bool a_enabled);
6211
6212WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6213wuffs_base__io_transformer__transform_io(
6214 wuffs_base__io_transformer* self,
6215 wuffs_base__io_buffer* a_dst,
6216 wuffs_base__io_buffer* a_src,
6217 wuffs_base__slice_u8 a_workbuf);
6218
6219WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6220wuffs_base__io_transformer__workbuf_len(
6221 const wuffs_base__io_transformer* self);
6222
6223#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6224
6225struct wuffs_base__io_transformer__struct {
6226 struct {
6227 uint32_t magic;
6228 uint32_t active_coroutine;
6229 wuffs_base__vtable first_vtable;
6230 } private_impl;
6231
6232#ifdef __cplusplus
6233#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6234 using unique_ptr = std::unique_ptr<wuffs_base__io_transformer, decltype(&free)>;
6235#endif
6236
6237 inline wuffs_base__empty_struct
6238 set_quirk_enabled(
6239 uint32_t a_quirk,
6240 bool a_enabled) {
6241 return wuffs_base__io_transformer__set_quirk_enabled(
6242 this, a_quirk, a_enabled);
6243 }
6244
6245 inline wuffs_base__status
6246 transform_io(
6247 wuffs_base__io_buffer* a_dst,
6248 wuffs_base__io_buffer* a_src,
6249 wuffs_base__slice_u8 a_workbuf) {
6250 return wuffs_base__io_transformer__transform_io(
6251 this, a_dst, a_src, a_workbuf);
6252 }
6253
6254 inline wuffs_base__range_ii_u64
6255 workbuf_len() const {
6256 return wuffs_base__io_transformer__workbuf_len(this);
6257 }
6258
6259#endif // __cplusplus
6260}; // struct wuffs_base__io_transformer__struct
6261
6262#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6263
6264// --------
6265
6266extern const char wuffs_base__token_decoder__vtable_name[];
6267
6268typedef struct wuffs_base__token_decoder__func_ptrs__struct {
6269 wuffs_base__status (*decode_tokens)(
6270 void* self,
6271 wuffs_base__token_buffer* a_dst,
6272 wuffs_base__io_buffer* a_src,
6273 wuffs_base__slice_u8 a_workbuf);
6274 wuffs_base__empty_struct (*set_quirk_enabled)(
6275 void* self,
6276 uint32_t a_quirk,
6277 bool a_enabled);
6278 wuffs_base__range_ii_u64 (*workbuf_len)(
6279 const void* self);
6280} wuffs_base__token_decoder__func_ptrs;
6281
6282typedef struct wuffs_base__token_decoder__struct wuffs_base__token_decoder;
6283
6284WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6285wuffs_base__token_decoder__decode_tokens(
6286 wuffs_base__token_decoder* self,
6287 wuffs_base__token_buffer* a_dst,
6288 wuffs_base__io_buffer* a_src,
6289 wuffs_base__slice_u8 a_workbuf);
6290
6291WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6292wuffs_base__token_decoder__set_quirk_enabled(
6293 wuffs_base__token_decoder* self,
6294 uint32_t a_quirk,
6295 bool a_enabled);
6296
6297WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6298wuffs_base__token_decoder__workbuf_len(
6299 const wuffs_base__token_decoder* self);
6300
6301#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6302
6303struct wuffs_base__token_decoder__struct {
6304 struct {
6305 uint32_t magic;
6306 uint32_t active_coroutine;
6307 wuffs_base__vtable first_vtable;
6308 } private_impl;
6309
6310#ifdef __cplusplus
6311#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6312 using unique_ptr = std::unique_ptr<wuffs_base__token_decoder, decltype(&free)>;
6313#endif
6314
6315 inline wuffs_base__status
6316 decode_tokens(
6317 wuffs_base__token_buffer* a_dst,
6318 wuffs_base__io_buffer* a_src,
6319 wuffs_base__slice_u8 a_workbuf) {
6320 return wuffs_base__token_decoder__decode_tokens(
6321 this, a_dst, a_src, a_workbuf);
6322 }
6323
6324 inline wuffs_base__empty_struct
6325 set_quirk_enabled(
6326 uint32_t a_quirk,
6327 bool a_enabled) {
6328 return wuffs_base__token_decoder__set_quirk_enabled(
6329 this, a_quirk, a_enabled);
6330 }
6331
6332 inline wuffs_base__range_ii_u64
6333 workbuf_len() const {
6334 return wuffs_base__token_decoder__workbuf_len(this);
6335 }
6336
6337#endif // __cplusplus
6338}; // struct wuffs_base__token_decoder__struct
6339
6340#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6341
6342// ----------------
6343
6344#ifdef __cplusplus
6345} // extern "C"
6346#endif
6347
Nigel Taofe9d08f2022-10-28 17:30:51 +11006348#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) || defined(WUFFS_NONMONOLITHIC)
6349
Nigel Taoe360a532021-04-05 22:47:03 +10006350// ---------------- Status Codes
6351
6352// ---------------- Public Consts
6353
6354// ---------------- Struct Declarations
6355
6356typedef struct wuffs_adler32__hasher__struct wuffs_adler32__hasher;
6357
6358#ifdef __cplusplus
6359extern "C" {
6360#endif
6361
6362// ---------------- Public Initializer Prototypes
6363
6364// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6365// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6366//
6367// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6368// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6369
6370wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6371wuffs_adler32__hasher__initialize(
6372 wuffs_adler32__hasher* self,
6373 size_t sizeof_star_self,
6374 uint64_t wuffs_version,
6375 uint32_t options);
6376
6377size_t
6378sizeof__wuffs_adler32__hasher();
6379
6380// ---------------- Allocs
6381
6382// These functions allocate and initialize Wuffs structs. They return NULL if
6383// memory allocation fails. If they return non-NULL, there is no need to call
6384// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6385// calling free on the returned pointer. That pointer is effectively a C++
6386// std::unique_ptr<T, decltype(&free)>.
6387
6388wuffs_adler32__hasher*
6389wuffs_adler32__hasher__alloc();
6390
6391static inline wuffs_base__hasher_u32*
6392wuffs_adler32__hasher__alloc_as__wuffs_base__hasher_u32() {
6393 return (wuffs_base__hasher_u32*)(wuffs_adler32__hasher__alloc());
6394}
6395
6396// ---------------- Upcasts
6397
6398static inline wuffs_base__hasher_u32*
6399wuffs_adler32__hasher__upcast_as__wuffs_base__hasher_u32(
6400 wuffs_adler32__hasher* p) {
6401 return (wuffs_base__hasher_u32*)p;
6402}
6403
6404// ---------------- Public Function Prototypes
6405
6406WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6407wuffs_adler32__hasher__set_quirk_enabled(
6408 wuffs_adler32__hasher* self,
6409 uint32_t a_quirk,
6410 bool a_enabled);
6411
6412WUFFS_BASE__MAYBE_STATIC uint32_t
6413wuffs_adler32__hasher__update_u32(
6414 wuffs_adler32__hasher* self,
6415 wuffs_base__slice_u8 a_x);
6416
6417#ifdef __cplusplus
6418} // extern "C"
6419#endif
6420
6421// ---------------- Struct Definitions
6422
6423// These structs' fields, and the sizeof them, are private implementation
6424// details that aren't guaranteed to be stable across Wuffs versions.
6425//
6426// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6427
6428#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6429
6430struct wuffs_adler32__hasher__struct {
6431 // Do not access the private_impl's or private_data's fields directly. There
6432 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6433 // the wuffs_foo__bar__baz functions.
6434 //
6435 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6436 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6437
6438 struct {
6439 uint32_t magic;
6440 uint32_t active_coroutine;
6441 wuffs_base__vtable vtable_for__wuffs_base__hasher_u32;
6442 wuffs_base__vtable null_vtable;
6443
6444 uint32_t f_state;
6445 bool f_started;
6446
6447 wuffs_base__empty_struct (*choosy_up)(
6448 wuffs_adler32__hasher* self,
6449 wuffs_base__slice_u8 a_x);
6450 } private_impl;
6451
6452#ifdef __cplusplus
6453#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6454 using unique_ptr = std::unique_ptr<wuffs_adler32__hasher, decltype(&free)>;
6455
6456 // On failure, the alloc_etc functions return nullptr. They don't throw.
6457
6458 static inline unique_ptr
6459 alloc() {
6460 return unique_ptr(wuffs_adler32__hasher__alloc(), &free);
6461 }
6462
6463 static inline wuffs_base__hasher_u32::unique_ptr
6464 alloc_as__wuffs_base__hasher_u32() {
6465 return wuffs_base__hasher_u32::unique_ptr(
6466 wuffs_adler32__hasher__alloc_as__wuffs_base__hasher_u32(), &free);
6467 }
6468#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6469
6470#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6471 // Disallow constructing or copying an object via standard C++ mechanisms,
6472 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
6473 // size and field layout is not part of the public, stable, memory-safe API.
6474 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
6475 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
6476 // their first argument) rather than tweaking bar.private_impl.qux fields.
6477 //
6478 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
6479 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
6480 // order to provide convenience methods. These forward on "this", so that you
6481 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
6482 wuffs_adler32__hasher__struct() = delete;
6483 wuffs_adler32__hasher__struct(const wuffs_adler32__hasher__struct&) = delete;
6484 wuffs_adler32__hasher__struct& operator=(
6485 const wuffs_adler32__hasher__struct&) = delete;
6486#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6487
6488#if !defined(WUFFS_IMPLEMENTATION)
6489 // As above, the size of the struct is not part of the public API, and unless
6490 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
6491 // allocated, not stack allocated. Its size is not intended to be known at
6492 // compile time, but it is unfortunately divulged as a side effect of
6493 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
6494 // instead of "sizeof T", invoking the operator. To make the two values
6495 // different, so that passing the latter will be rejected by the initialize
6496 // function, we add an arbitrary amount of dead weight.
6497 uint8_t dead_weight[123000000]; // 123 MB.
6498#endif // !defined(WUFFS_IMPLEMENTATION)
6499
6500 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6501 initialize(
6502 size_t sizeof_star_self,
6503 uint64_t wuffs_version,
6504 uint32_t options) {
6505 return wuffs_adler32__hasher__initialize(
6506 this, sizeof_star_self, wuffs_version, options);
6507 }
6508
6509 inline wuffs_base__hasher_u32*
6510 upcast_as__wuffs_base__hasher_u32() {
6511 return (wuffs_base__hasher_u32*)this;
6512 }
6513
6514 inline wuffs_base__empty_struct
6515 set_quirk_enabled(
6516 uint32_t a_quirk,
6517 bool a_enabled) {
6518 return wuffs_adler32__hasher__set_quirk_enabled(this, a_quirk, a_enabled);
6519 }
6520
6521 inline uint32_t
6522 update_u32(
6523 wuffs_base__slice_u8 a_x) {
6524 return wuffs_adler32__hasher__update_u32(this, a_x);
6525 }
6526
6527#endif // __cplusplus
6528}; // struct wuffs_adler32__hasher__struct
6529
6530#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6531
Nigel Taofe9d08f2022-10-28 17:30:51 +11006532#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32) || defined(WUFFS_NONMONOLITHIC)
6533
6534#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) || defined(WUFFS_NONMONOLITHIC)
6535
Nigel Taoe360a532021-04-05 22:47:03 +10006536// ---------------- Status Codes
6537
6538extern const char wuffs_bmp__error__bad_header[];
6539extern const char wuffs_bmp__error__bad_rle_compression[];
6540extern const char wuffs_bmp__error__unsupported_bmp_file[];
6541
6542// ---------------- Public Consts
6543
6544#define WUFFS_BMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
6545
6546// ---------------- Struct Declarations
6547
6548typedef struct wuffs_bmp__decoder__struct wuffs_bmp__decoder;
6549
6550#ifdef __cplusplus
6551extern "C" {
6552#endif
6553
6554// ---------------- Public Initializer Prototypes
6555
6556// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6557// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6558//
6559// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6560// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6561
6562wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6563wuffs_bmp__decoder__initialize(
6564 wuffs_bmp__decoder* self,
6565 size_t sizeof_star_self,
6566 uint64_t wuffs_version,
6567 uint32_t options);
6568
6569size_t
6570sizeof__wuffs_bmp__decoder();
6571
6572// ---------------- Allocs
6573
6574// These functions allocate and initialize Wuffs structs. They return NULL if
6575// memory allocation fails. If they return non-NULL, there is no need to call
6576// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6577// calling free on the returned pointer. That pointer is effectively a C++
6578// std::unique_ptr<T, decltype(&free)>.
6579
6580wuffs_bmp__decoder*
6581wuffs_bmp__decoder__alloc();
6582
6583static inline wuffs_base__image_decoder*
6584wuffs_bmp__decoder__alloc_as__wuffs_base__image_decoder() {
6585 return (wuffs_base__image_decoder*)(wuffs_bmp__decoder__alloc());
6586}
6587
6588// ---------------- Upcasts
6589
6590static inline wuffs_base__image_decoder*
6591wuffs_bmp__decoder__upcast_as__wuffs_base__image_decoder(
6592 wuffs_bmp__decoder* p) {
6593 return (wuffs_base__image_decoder*)p;
6594}
6595
6596// ---------------- Public Function Prototypes
6597
6598WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6599wuffs_bmp__decoder__set_quirk_enabled(
6600 wuffs_bmp__decoder* self,
6601 uint32_t a_quirk,
6602 bool a_enabled);
6603
6604WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6605wuffs_bmp__decoder__decode_image_config(
6606 wuffs_bmp__decoder* self,
6607 wuffs_base__image_config* a_dst,
6608 wuffs_base__io_buffer* a_src);
6609
6610WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6611wuffs_bmp__decoder__decode_frame_config(
6612 wuffs_bmp__decoder* self,
6613 wuffs_base__frame_config* a_dst,
6614 wuffs_base__io_buffer* a_src);
6615
6616WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6617wuffs_bmp__decoder__decode_frame(
6618 wuffs_bmp__decoder* self,
6619 wuffs_base__pixel_buffer* a_dst,
6620 wuffs_base__io_buffer* a_src,
6621 wuffs_base__pixel_blend a_blend,
6622 wuffs_base__slice_u8 a_workbuf,
6623 wuffs_base__decode_frame_options* a_opts);
6624
6625WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
6626wuffs_bmp__decoder__frame_dirty_rect(
6627 const wuffs_bmp__decoder* self);
6628
6629WUFFS_BASE__MAYBE_STATIC uint32_t
6630wuffs_bmp__decoder__num_animation_loops(
6631 const wuffs_bmp__decoder* self);
6632
6633WUFFS_BASE__MAYBE_STATIC uint64_t
6634wuffs_bmp__decoder__num_decoded_frame_configs(
6635 const wuffs_bmp__decoder* self);
6636
6637WUFFS_BASE__MAYBE_STATIC uint64_t
6638wuffs_bmp__decoder__num_decoded_frames(
6639 const wuffs_bmp__decoder* self);
6640
6641WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6642wuffs_bmp__decoder__restart_frame(
6643 wuffs_bmp__decoder* self,
6644 uint64_t a_index,
6645 uint64_t a_io_position);
6646
6647WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6648wuffs_bmp__decoder__set_report_metadata(
6649 wuffs_bmp__decoder* self,
6650 uint32_t a_fourcc,
6651 bool a_report);
6652
6653WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6654wuffs_bmp__decoder__tell_me_more(
6655 wuffs_bmp__decoder* self,
6656 wuffs_base__io_buffer* a_dst,
6657 wuffs_base__more_information* a_minfo,
6658 wuffs_base__io_buffer* a_src);
6659
6660WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6661wuffs_bmp__decoder__workbuf_len(
6662 const wuffs_bmp__decoder* self);
6663
6664#ifdef __cplusplus
6665} // extern "C"
6666#endif
6667
6668// ---------------- Struct Definitions
6669
6670// These structs' fields, and the sizeof them, are private implementation
6671// details that aren't guaranteed to be stable across Wuffs versions.
6672//
6673// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6674
6675#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6676
6677struct wuffs_bmp__decoder__struct {
6678 // Do not access the private_impl's or private_data's fields directly. There
6679 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6680 // the wuffs_foo__bar__baz functions.
6681 //
6682 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6683 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6684
6685 struct {
6686 uint32_t magic;
6687 uint32_t active_coroutine;
6688 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
6689 wuffs_base__vtable null_vtable;
6690
6691 uint32_t f_width;
6692 uint32_t f_height;
6693 uint8_t f_call_sequence;
6694 bool f_top_down;
6695 uint32_t f_pad_per_row;
6696 uint32_t f_src_pixfmt;
6697 uint32_t f_io_redirect_fourcc;
6698 uint64_t f_io_redirect_pos;
6699 uint64_t f_frame_config_io_position;
6700 uint32_t f_bitmap_info_len;
6701 uint32_t f_padding;
6702 uint32_t f_bits_per_pixel;
6703 uint32_t f_compression;
6704 uint32_t f_channel_masks[4];
6705 uint8_t f_channel_shifts[4];
6706 uint8_t f_channel_num_bits[4];
6707 uint32_t f_dst_x;
6708 uint32_t f_dst_y;
6709 uint32_t f_dst_y_inc;
6710 uint32_t f_pending_pad;
6711 uint32_t f_rle_state;
6712 uint32_t f_rle_length;
6713 uint8_t f_rle_delta_x;
6714 bool f_rle_padded;
6715 wuffs_base__pixel_swizzler f_swizzler;
6716
6717 uint32_t p_decode_image_config[1];
6718 uint32_t p_decode_frame_config[1];
6719 uint32_t p_decode_frame[1];
6720 uint32_t p_read_palette[1];
6721 } private_impl;
6722
6723 struct {
6724 uint8_t f_scratch[2048];
6725 uint8_t f_src_palette[1024];
6726
6727 struct {
6728 uint64_t scratch;
6729 } s_decode_image_config[1];
6730 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10006731 uint64_t scratch;
6732 } s_decode_frame[1];
6733 struct {
6734 uint32_t v_i;
6735 uint64_t scratch;
6736 } s_read_palette[1];
6737 } private_data;
6738
6739#ifdef __cplusplus
6740#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6741 using unique_ptr = std::unique_ptr<wuffs_bmp__decoder, decltype(&free)>;
6742
6743 // On failure, the alloc_etc functions return nullptr. They don't throw.
6744
6745 static inline unique_ptr
6746 alloc() {
6747 return unique_ptr(wuffs_bmp__decoder__alloc(), &free);
6748 }
6749
6750 static inline wuffs_base__image_decoder::unique_ptr
6751 alloc_as__wuffs_base__image_decoder() {
6752 return wuffs_base__image_decoder::unique_ptr(
6753 wuffs_bmp__decoder__alloc_as__wuffs_base__image_decoder(), &free);
6754 }
6755#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
6756
6757#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6758 // Disallow constructing or copying an object via standard C++ mechanisms,
6759 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
6760 // size and field layout is not part of the public, stable, memory-safe API.
6761 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
6762 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
6763 // their first argument) rather than tweaking bar.private_impl.qux fields.
6764 //
6765 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
6766 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
6767 // order to provide convenience methods. These forward on "this", so that you
6768 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
6769 wuffs_bmp__decoder__struct() = delete;
6770 wuffs_bmp__decoder__struct(const wuffs_bmp__decoder__struct&) = delete;
6771 wuffs_bmp__decoder__struct& operator=(
6772 const wuffs_bmp__decoder__struct&) = delete;
6773#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
6774
6775#if !defined(WUFFS_IMPLEMENTATION)
6776 // As above, the size of the struct is not part of the public API, and unless
6777 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
6778 // allocated, not stack allocated. Its size is not intended to be known at
6779 // compile time, but it is unfortunately divulged as a side effect of
6780 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
6781 // instead of "sizeof T", invoking the operator. To make the two values
6782 // different, so that passing the latter will be rejected by the initialize
6783 // function, we add an arbitrary amount of dead weight.
6784 uint8_t dead_weight[123000000]; // 123 MB.
6785#endif // !defined(WUFFS_IMPLEMENTATION)
6786
6787 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6788 initialize(
6789 size_t sizeof_star_self,
6790 uint64_t wuffs_version,
6791 uint32_t options) {
6792 return wuffs_bmp__decoder__initialize(
6793 this, sizeof_star_self, wuffs_version, options);
6794 }
6795
6796 inline wuffs_base__image_decoder*
6797 upcast_as__wuffs_base__image_decoder() {
6798 return (wuffs_base__image_decoder*)this;
6799 }
6800
6801 inline wuffs_base__empty_struct
6802 set_quirk_enabled(
6803 uint32_t a_quirk,
6804 bool a_enabled) {
6805 return wuffs_bmp__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
6806 }
6807
6808 inline wuffs_base__status
6809 decode_image_config(
6810 wuffs_base__image_config* a_dst,
6811 wuffs_base__io_buffer* a_src) {
6812 return wuffs_bmp__decoder__decode_image_config(this, a_dst, a_src);
6813 }
6814
6815 inline wuffs_base__status
6816 decode_frame_config(
6817 wuffs_base__frame_config* a_dst,
6818 wuffs_base__io_buffer* a_src) {
6819 return wuffs_bmp__decoder__decode_frame_config(this, a_dst, a_src);
6820 }
6821
6822 inline wuffs_base__status
6823 decode_frame(
6824 wuffs_base__pixel_buffer* a_dst,
6825 wuffs_base__io_buffer* a_src,
6826 wuffs_base__pixel_blend a_blend,
6827 wuffs_base__slice_u8 a_workbuf,
6828 wuffs_base__decode_frame_options* a_opts) {
6829 return wuffs_bmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
6830 }
6831
6832 inline wuffs_base__rect_ie_u32
6833 frame_dirty_rect() const {
6834 return wuffs_bmp__decoder__frame_dirty_rect(this);
6835 }
6836
6837 inline uint32_t
6838 num_animation_loops() const {
6839 return wuffs_bmp__decoder__num_animation_loops(this);
6840 }
6841
6842 inline uint64_t
6843 num_decoded_frame_configs() const {
6844 return wuffs_bmp__decoder__num_decoded_frame_configs(this);
6845 }
6846
6847 inline uint64_t
6848 num_decoded_frames() const {
6849 return wuffs_bmp__decoder__num_decoded_frames(this);
6850 }
6851
6852 inline wuffs_base__status
6853 restart_frame(
6854 uint64_t a_index,
6855 uint64_t a_io_position) {
6856 return wuffs_bmp__decoder__restart_frame(this, a_index, a_io_position);
6857 }
6858
6859 inline wuffs_base__empty_struct
6860 set_report_metadata(
6861 uint32_t a_fourcc,
6862 bool a_report) {
6863 return wuffs_bmp__decoder__set_report_metadata(this, a_fourcc, a_report);
6864 }
6865
6866 inline wuffs_base__status
6867 tell_me_more(
6868 wuffs_base__io_buffer* a_dst,
6869 wuffs_base__more_information* a_minfo,
6870 wuffs_base__io_buffer* a_src) {
6871 return wuffs_bmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
6872 }
6873
6874 inline wuffs_base__range_ii_u64
6875 workbuf_len() const {
6876 return wuffs_bmp__decoder__workbuf_len(this);
6877 }
6878
6879#endif // __cplusplus
6880}; // struct wuffs_bmp__decoder__struct
6881
6882#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6883
Nigel Taofe9d08f2022-10-28 17:30:51 +11006884#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP) || defined(WUFFS_NONMONOLITHIC)
6885
6886#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) || defined(WUFFS_NONMONOLITHIC)
6887
Nigel Taoe360a532021-04-05 22:47:03 +10006888// ---------------- Status Codes
6889
Nigel Tao123a5c62022-06-03 14:17:20 +10006890extern const char wuffs_bzip2__error__bad_huffman_code_over_subscribed[];
6891extern const char wuffs_bzip2__error__bad_huffman_code_under_subscribed[];
6892extern const char wuffs_bzip2__error__bad_block_header[];
6893extern const char wuffs_bzip2__error__bad_block_length[];
6894extern const char wuffs_bzip2__error__bad_checksum[];
6895extern const char wuffs_bzip2__error__bad_header[];
Nigel Tao123a5c62022-06-03 14:17:20 +10006896extern const char wuffs_bzip2__error__bad_number_of_sections[];
Nigel Tao123a5c62022-06-03 14:17:20 +10006897extern const char wuffs_bzip2__error__unsupported_block_randomization[];
6898
6899// ---------------- Public Consts
6900
6901#define WUFFS_BZIP2__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
6902
6903// ---------------- Struct Declarations
6904
6905typedef struct wuffs_bzip2__decoder__struct wuffs_bzip2__decoder;
6906
6907#ifdef __cplusplus
6908extern "C" {
6909#endif
6910
6911// ---------------- Public Initializer Prototypes
6912
6913// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
6914// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
6915//
6916// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
6917// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
6918
6919wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
6920wuffs_bzip2__decoder__initialize(
6921 wuffs_bzip2__decoder* self,
6922 size_t sizeof_star_self,
6923 uint64_t wuffs_version,
6924 uint32_t options);
6925
6926size_t
6927sizeof__wuffs_bzip2__decoder();
6928
6929// ---------------- Allocs
6930
6931// These functions allocate and initialize Wuffs structs. They return NULL if
6932// memory allocation fails. If they return non-NULL, there is no need to call
6933// wuffs_foo__bar__initialize, but the caller is responsible for eventually
6934// calling free on the returned pointer. That pointer is effectively a C++
6935// std::unique_ptr<T, decltype(&free)>.
6936
6937wuffs_bzip2__decoder*
6938wuffs_bzip2__decoder__alloc();
6939
6940static inline wuffs_base__io_transformer*
6941wuffs_bzip2__decoder__alloc_as__wuffs_base__io_transformer() {
6942 return (wuffs_base__io_transformer*)(wuffs_bzip2__decoder__alloc());
6943}
6944
6945// ---------------- Upcasts
6946
6947static inline wuffs_base__io_transformer*
6948wuffs_bzip2__decoder__upcast_as__wuffs_base__io_transformer(
6949 wuffs_bzip2__decoder* p) {
6950 return (wuffs_base__io_transformer*)p;
6951}
6952
6953// ---------------- Public Function Prototypes
6954
6955WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
6956wuffs_bzip2__decoder__set_quirk_enabled(
6957 wuffs_bzip2__decoder* self,
6958 uint32_t a_quirk,
6959 bool a_enabled);
6960
6961WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
6962wuffs_bzip2__decoder__workbuf_len(
6963 const wuffs_bzip2__decoder* self);
6964
6965WUFFS_BASE__MAYBE_STATIC wuffs_base__status
6966wuffs_bzip2__decoder__transform_io(
6967 wuffs_bzip2__decoder* self,
6968 wuffs_base__io_buffer* a_dst,
6969 wuffs_base__io_buffer* a_src,
6970 wuffs_base__slice_u8 a_workbuf);
6971
6972#ifdef __cplusplus
6973} // extern "C"
6974#endif
6975
6976// ---------------- Struct Definitions
6977
6978// These structs' fields, and the sizeof them, are private implementation
6979// details that aren't guaranteed to be stable across Wuffs versions.
6980//
6981// See https://en.wikipedia.org/wiki/Opaque_pointer#C
6982
6983#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
6984
6985struct wuffs_bzip2__decoder__struct {
6986 // Do not access the private_impl's or private_data's fields directly. There
6987 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
6988 // the wuffs_foo__bar__baz functions.
6989 //
6990 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
6991 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
6992
6993 struct {
6994 uint32_t magic;
6995 uint32_t active_coroutine;
6996 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
6997 wuffs_base__vtable null_vtable;
6998
6999 uint32_t f_bits;
7000 uint32_t f_n_bits;
7001 uint32_t f_max_incl_block_size;
7002 uint32_t f_block_size;
7003 bool f_decode_huffman_finished;
7004 uint8_t f_decode_huffman_which;
7005 uint32_t f_decode_huffman_ticks;
7006 uint32_t f_decode_huffman_section;
7007 uint32_t f_decode_huffman_run_shift;
7008 uint32_t f_flush_pointer;
7009 uint32_t f_flush_repeat_count;
7010 uint8_t f_flush_prev;
7011 bool f_ignore_checksum;
7012 uint32_t f_final_checksum_have;
7013 uint32_t f_block_checksum_have;
7014 uint32_t f_block_checksum_want;
7015 uint32_t f_original_pointer;
7016 uint32_t f_num_symbols;
7017 uint32_t f_num_huffman_codes;
7018 uint32_t f_num_sections;
7019 uint32_t f_code_lengths_bitmask;
7020
7021 uint32_t p_transform_io[1];
7022 uint32_t p_prepare_block[1];
7023 uint32_t p_read_code_lengths[1];
7024 uint32_t p_flush_slow[1];
7025 uint32_t p_decode_huffman_slow[1];
7026 } private_impl;
7027
7028 struct {
7029 uint32_t f_scratch;
7030 uint32_t f_letter_counts[256];
7031 uint8_t f_presence[256];
7032 uint8_t f_mtft[256];
7033 uint8_t f_huffman_selectors[32768];
Nigel Taoa8205c22022-07-10 16:01:15 +10007034 uint16_t f_huffman_trees[6][257][2];
Nigel Tao123a5c62022-06-03 14:17:20 +10007035 uint16_t f_huffman_tables[6][256];
7036 uint32_t f_bwt[1048576];
7037
7038 struct {
7039 uint32_t v_i;
7040 uint64_t v_tag;
7041 uint32_t v_final_checksum_want;
7042 } s_transform_io[1];
7043 struct {
7044 uint32_t v_i;
7045 uint32_t v_selector;
7046 } s_prepare_block[1];
7047 struct {
7048 uint32_t v_i;
7049 uint32_t v_code_length;
7050 } s_read_code_lengths[1];
7051 struct {
7052 uint32_t v_flush_pointer;
7053 uint32_t v_flush_repeat_count;
7054 uint8_t v_flush_prev;
7055 uint32_t v_block_checksum_have;
7056 uint32_t v_block_size;
7057 uint8_t v_curr;
7058 uint64_t scratch;
7059 } s_flush_slow[1];
7060 struct {
7061 uint32_t v_node_index;
7062 } s_decode_huffman_slow[1];
7063 } private_data;
7064
7065#ifdef __cplusplus
7066#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7067 using unique_ptr = std::unique_ptr<wuffs_bzip2__decoder, decltype(&free)>;
7068
7069 // On failure, the alloc_etc functions return nullptr. They don't throw.
7070
7071 static inline unique_ptr
7072 alloc() {
7073 return unique_ptr(wuffs_bzip2__decoder__alloc(), &free);
7074 }
7075
7076 static inline wuffs_base__io_transformer::unique_ptr
7077 alloc_as__wuffs_base__io_transformer() {
7078 return wuffs_base__io_transformer::unique_ptr(
7079 wuffs_bzip2__decoder__alloc_as__wuffs_base__io_transformer(), &free);
7080 }
7081#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7082
7083#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7084 // Disallow constructing or copying an object via standard C++ mechanisms,
7085 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7086 // size and field layout is not part of the public, stable, memory-safe API.
7087 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7088 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7089 // their first argument) rather than tweaking bar.private_impl.qux fields.
7090 //
7091 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7092 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7093 // order to provide convenience methods. These forward on "this", so that you
7094 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7095 wuffs_bzip2__decoder__struct() = delete;
7096 wuffs_bzip2__decoder__struct(const wuffs_bzip2__decoder__struct&) = delete;
7097 wuffs_bzip2__decoder__struct& operator=(
7098 const wuffs_bzip2__decoder__struct&) = delete;
7099#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7100
7101#if !defined(WUFFS_IMPLEMENTATION)
7102 // As above, the size of the struct is not part of the public API, and unless
7103 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7104 // allocated, not stack allocated. Its size is not intended to be known at
7105 // compile time, but it is unfortunately divulged as a side effect of
7106 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7107 // instead of "sizeof T", invoking the operator. To make the two values
7108 // different, so that passing the latter will be rejected by the initialize
7109 // function, we add an arbitrary amount of dead weight.
7110 uint8_t dead_weight[123000000]; // 123 MB.
7111#endif // !defined(WUFFS_IMPLEMENTATION)
7112
7113 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7114 initialize(
7115 size_t sizeof_star_self,
7116 uint64_t wuffs_version,
7117 uint32_t options) {
7118 return wuffs_bzip2__decoder__initialize(
7119 this, sizeof_star_self, wuffs_version, options);
7120 }
7121
7122 inline wuffs_base__io_transformer*
7123 upcast_as__wuffs_base__io_transformer() {
7124 return (wuffs_base__io_transformer*)this;
7125 }
7126
7127 inline wuffs_base__empty_struct
7128 set_quirk_enabled(
7129 uint32_t a_quirk,
7130 bool a_enabled) {
7131 return wuffs_bzip2__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
7132 }
7133
7134 inline wuffs_base__range_ii_u64
7135 workbuf_len() const {
7136 return wuffs_bzip2__decoder__workbuf_len(this);
7137 }
7138
7139 inline wuffs_base__status
7140 transform_io(
7141 wuffs_base__io_buffer* a_dst,
7142 wuffs_base__io_buffer* a_src,
7143 wuffs_base__slice_u8 a_workbuf) {
7144 return wuffs_bzip2__decoder__transform_io(this, a_dst, a_src, a_workbuf);
7145 }
7146
7147#endif // __cplusplus
7148}; // struct wuffs_bzip2__decoder__struct
7149
7150#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7151
Nigel Taofe9d08f2022-10-28 17:30:51 +11007152#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2) || defined(WUFFS_NONMONOLITHIC)
7153
7154#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) || defined(WUFFS_NONMONOLITHIC)
7155
Nigel Tao123a5c62022-06-03 14:17:20 +10007156// ---------------- Status Codes
7157
Nigel Taoe360a532021-04-05 22:47:03 +10007158extern const char wuffs_cbor__error__bad_input[];
7159extern const char wuffs_cbor__error__unsupported_recursion_depth[];
7160
7161// ---------------- Public Consts
7162
7163#define WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
7164
7165#define WUFFS_CBOR__DECODER_DEPTH_MAX_INCL 1024
7166
7167#define WUFFS_CBOR__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 2
7168
7169#define WUFFS_CBOR__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 9
7170
7171#define WUFFS_CBOR__TOKEN_VALUE_MAJOR 787997
7172
7173#define WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK 262143
7174
7175#define WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X 16777216
7176
7177#define WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE 8388608
7178
7179#define WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG 4194304
7180
7181// ---------------- Struct Declarations
7182
7183typedef struct wuffs_cbor__decoder__struct wuffs_cbor__decoder;
7184
7185#ifdef __cplusplus
7186extern "C" {
7187#endif
7188
7189// ---------------- Public Initializer Prototypes
7190
7191// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7192// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7193//
7194// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7195// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7196
7197wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7198wuffs_cbor__decoder__initialize(
7199 wuffs_cbor__decoder* self,
7200 size_t sizeof_star_self,
7201 uint64_t wuffs_version,
7202 uint32_t options);
7203
7204size_t
7205sizeof__wuffs_cbor__decoder();
7206
7207// ---------------- Allocs
7208
7209// These functions allocate and initialize Wuffs structs. They return NULL if
7210// memory allocation fails. If they return non-NULL, there is no need to call
7211// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7212// calling free on the returned pointer. That pointer is effectively a C++
7213// std::unique_ptr<T, decltype(&free)>.
7214
7215wuffs_cbor__decoder*
7216wuffs_cbor__decoder__alloc();
7217
7218static inline wuffs_base__token_decoder*
7219wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder() {
7220 return (wuffs_base__token_decoder*)(wuffs_cbor__decoder__alloc());
7221}
7222
7223// ---------------- Upcasts
7224
7225static inline wuffs_base__token_decoder*
7226wuffs_cbor__decoder__upcast_as__wuffs_base__token_decoder(
7227 wuffs_cbor__decoder* p) {
7228 return (wuffs_base__token_decoder*)p;
7229}
7230
7231// ---------------- Public Function Prototypes
7232
7233WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7234wuffs_cbor__decoder__set_quirk_enabled(
7235 wuffs_cbor__decoder* self,
7236 uint32_t a_quirk,
7237 bool a_enabled);
7238
7239WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7240wuffs_cbor__decoder__workbuf_len(
7241 const wuffs_cbor__decoder* self);
7242
7243WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7244wuffs_cbor__decoder__decode_tokens(
7245 wuffs_cbor__decoder* self,
7246 wuffs_base__token_buffer* a_dst,
7247 wuffs_base__io_buffer* a_src,
7248 wuffs_base__slice_u8 a_workbuf);
7249
7250#ifdef __cplusplus
7251} // extern "C"
7252#endif
7253
7254// ---------------- Struct Definitions
7255
7256// These structs' fields, and the sizeof them, are private implementation
7257// details that aren't guaranteed to be stable across Wuffs versions.
7258//
7259// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7260
7261#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7262
7263struct wuffs_cbor__decoder__struct {
7264 // Do not access the private_impl's or private_data's fields directly. There
7265 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7266 // the wuffs_foo__bar__baz functions.
7267 //
7268 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7269 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7270
7271 struct {
7272 uint32_t magic;
7273 uint32_t active_coroutine;
7274 wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
7275 wuffs_base__vtable null_vtable;
7276
7277 bool f_end_of_data;
7278
7279 uint32_t p_decode_tokens[1];
7280 } private_impl;
7281
7282 struct {
7283 uint32_t f_stack[64];
7284 uint64_t f_container_num_remaining[1024];
7285
7286 struct {
7287 uint64_t v_string_length;
7288 uint32_t v_depth;
Nigel Taoe360a532021-04-05 22:47:03 +10007289 bool v_tagged;
7290 uint8_t v_indefinite_string_major_type;
7291 } s_decode_tokens[1];
7292 } private_data;
7293
7294#ifdef __cplusplus
7295#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7296 using unique_ptr = std::unique_ptr<wuffs_cbor__decoder, decltype(&free)>;
7297
7298 // On failure, the alloc_etc functions return nullptr. They don't throw.
7299
7300 static inline unique_ptr
7301 alloc() {
7302 return unique_ptr(wuffs_cbor__decoder__alloc(), &free);
7303 }
7304
7305 static inline wuffs_base__token_decoder::unique_ptr
7306 alloc_as__wuffs_base__token_decoder() {
7307 return wuffs_base__token_decoder::unique_ptr(
7308 wuffs_cbor__decoder__alloc_as__wuffs_base__token_decoder(), &free);
7309 }
7310#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7311
7312#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7313 // Disallow constructing or copying an object via standard C++ mechanisms,
7314 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7315 // size and field layout is not part of the public, stable, memory-safe API.
7316 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7317 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7318 // their first argument) rather than tweaking bar.private_impl.qux fields.
7319 //
7320 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7321 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7322 // order to provide convenience methods. These forward on "this", so that you
7323 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7324 wuffs_cbor__decoder__struct() = delete;
7325 wuffs_cbor__decoder__struct(const wuffs_cbor__decoder__struct&) = delete;
7326 wuffs_cbor__decoder__struct& operator=(
7327 const wuffs_cbor__decoder__struct&) = delete;
7328#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7329
7330#if !defined(WUFFS_IMPLEMENTATION)
7331 // As above, the size of the struct is not part of the public API, and unless
7332 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7333 // allocated, not stack allocated. Its size is not intended to be known at
7334 // compile time, but it is unfortunately divulged as a side effect of
7335 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7336 // instead of "sizeof T", invoking the operator. To make the two values
7337 // different, so that passing the latter will be rejected by the initialize
7338 // function, we add an arbitrary amount of dead weight.
7339 uint8_t dead_weight[123000000]; // 123 MB.
7340#endif // !defined(WUFFS_IMPLEMENTATION)
7341
7342 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7343 initialize(
7344 size_t sizeof_star_self,
7345 uint64_t wuffs_version,
7346 uint32_t options) {
7347 return wuffs_cbor__decoder__initialize(
7348 this, sizeof_star_self, wuffs_version, options);
7349 }
7350
7351 inline wuffs_base__token_decoder*
7352 upcast_as__wuffs_base__token_decoder() {
7353 return (wuffs_base__token_decoder*)this;
7354 }
7355
7356 inline wuffs_base__empty_struct
7357 set_quirk_enabled(
7358 uint32_t a_quirk,
7359 bool a_enabled) {
7360 return wuffs_cbor__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
7361 }
7362
7363 inline wuffs_base__range_ii_u64
7364 workbuf_len() const {
7365 return wuffs_cbor__decoder__workbuf_len(this);
7366 }
7367
7368 inline wuffs_base__status
7369 decode_tokens(
7370 wuffs_base__token_buffer* a_dst,
7371 wuffs_base__io_buffer* a_src,
7372 wuffs_base__slice_u8 a_workbuf) {
7373 return wuffs_cbor__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
7374 }
7375
7376#endif // __cplusplus
7377}; // struct wuffs_cbor__decoder__struct
7378
7379#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7380
Nigel Taofe9d08f2022-10-28 17:30:51 +11007381#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR) || defined(WUFFS_NONMONOLITHIC)
7382
7383#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) || defined(WUFFS_NONMONOLITHIC)
7384
Nigel Taoe360a532021-04-05 22:47:03 +10007385// ---------------- Status Codes
7386
7387// ---------------- Public Consts
7388
7389// ---------------- Struct Declarations
7390
7391typedef struct wuffs_crc32__ieee_hasher__struct wuffs_crc32__ieee_hasher;
7392
7393#ifdef __cplusplus
7394extern "C" {
7395#endif
7396
7397// ---------------- Public Initializer Prototypes
7398
7399// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7400// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7401//
7402// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7403// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7404
7405wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7406wuffs_crc32__ieee_hasher__initialize(
7407 wuffs_crc32__ieee_hasher* self,
7408 size_t sizeof_star_self,
7409 uint64_t wuffs_version,
7410 uint32_t options);
7411
7412size_t
7413sizeof__wuffs_crc32__ieee_hasher();
7414
7415// ---------------- Allocs
7416
7417// These functions allocate and initialize Wuffs structs. They return NULL if
7418// memory allocation fails. If they return non-NULL, there is no need to call
7419// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7420// calling free on the returned pointer. That pointer is effectively a C++
7421// std::unique_ptr<T, decltype(&free)>.
7422
7423wuffs_crc32__ieee_hasher*
7424wuffs_crc32__ieee_hasher__alloc();
7425
7426static inline wuffs_base__hasher_u32*
7427wuffs_crc32__ieee_hasher__alloc_as__wuffs_base__hasher_u32() {
7428 return (wuffs_base__hasher_u32*)(wuffs_crc32__ieee_hasher__alloc());
7429}
7430
7431// ---------------- Upcasts
7432
7433static inline wuffs_base__hasher_u32*
7434wuffs_crc32__ieee_hasher__upcast_as__wuffs_base__hasher_u32(
7435 wuffs_crc32__ieee_hasher* p) {
7436 return (wuffs_base__hasher_u32*)p;
7437}
7438
7439// ---------------- Public Function Prototypes
7440
7441WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7442wuffs_crc32__ieee_hasher__set_quirk_enabled(
7443 wuffs_crc32__ieee_hasher* self,
7444 uint32_t a_quirk,
7445 bool a_enabled);
7446
7447WUFFS_BASE__MAYBE_STATIC uint32_t
7448wuffs_crc32__ieee_hasher__update_u32(
7449 wuffs_crc32__ieee_hasher* self,
7450 wuffs_base__slice_u8 a_x);
7451
7452#ifdef __cplusplus
7453} // extern "C"
7454#endif
7455
7456// ---------------- Struct Definitions
7457
7458// These structs' fields, and the sizeof them, are private implementation
7459// details that aren't guaranteed to be stable across Wuffs versions.
7460//
7461// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7462
7463#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7464
7465struct wuffs_crc32__ieee_hasher__struct {
7466 // Do not access the private_impl's or private_data's fields directly. There
7467 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7468 // the wuffs_foo__bar__baz functions.
7469 //
7470 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7471 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7472
7473 struct {
7474 uint32_t magic;
7475 uint32_t active_coroutine;
7476 wuffs_base__vtable vtable_for__wuffs_base__hasher_u32;
7477 wuffs_base__vtable null_vtable;
7478
7479 uint32_t f_state;
7480
7481 wuffs_base__empty_struct (*choosy_up)(
7482 wuffs_crc32__ieee_hasher* self,
7483 wuffs_base__slice_u8 a_x);
7484 } private_impl;
7485
7486#ifdef __cplusplus
7487#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7488 using unique_ptr = std::unique_ptr<wuffs_crc32__ieee_hasher, decltype(&free)>;
7489
7490 // On failure, the alloc_etc functions return nullptr. They don't throw.
7491
7492 static inline unique_ptr
7493 alloc() {
7494 return unique_ptr(wuffs_crc32__ieee_hasher__alloc(), &free);
7495 }
7496
7497 static inline wuffs_base__hasher_u32::unique_ptr
7498 alloc_as__wuffs_base__hasher_u32() {
7499 return wuffs_base__hasher_u32::unique_ptr(
7500 wuffs_crc32__ieee_hasher__alloc_as__wuffs_base__hasher_u32(), &free);
7501 }
7502#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7503
7504#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7505 // Disallow constructing or copying an object via standard C++ mechanisms,
7506 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7507 // size and field layout is not part of the public, stable, memory-safe API.
7508 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7509 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7510 // their first argument) rather than tweaking bar.private_impl.qux fields.
7511 //
7512 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7513 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7514 // order to provide convenience methods. These forward on "this", so that you
7515 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7516 wuffs_crc32__ieee_hasher__struct() = delete;
7517 wuffs_crc32__ieee_hasher__struct(const wuffs_crc32__ieee_hasher__struct&) = delete;
7518 wuffs_crc32__ieee_hasher__struct& operator=(
7519 const wuffs_crc32__ieee_hasher__struct&) = delete;
7520#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7521
7522#if !defined(WUFFS_IMPLEMENTATION)
7523 // As above, the size of the struct is not part of the public API, and unless
7524 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7525 // allocated, not stack allocated. Its size is not intended to be known at
7526 // compile time, but it is unfortunately divulged as a side effect of
7527 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7528 // instead of "sizeof T", invoking the operator. To make the two values
7529 // different, so that passing the latter will be rejected by the initialize
7530 // function, we add an arbitrary amount of dead weight.
7531 uint8_t dead_weight[123000000]; // 123 MB.
7532#endif // !defined(WUFFS_IMPLEMENTATION)
7533
7534 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7535 initialize(
7536 size_t sizeof_star_self,
7537 uint64_t wuffs_version,
7538 uint32_t options) {
7539 return wuffs_crc32__ieee_hasher__initialize(
7540 this, sizeof_star_self, wuffs_version, options);
7541 }
7542
7543 inline wuffs_base__hasher_u32*
7544 upcast_as__wuffs_base__hasher_u32() {
7545 return (wuffs_base__hasher_u32*)this;
7546 }
7547
7548 inline wuffs_base__empty_struct
7549 set_quirk_enabled(
7550 uint32_t a_quirk,
7551 bool a_enabled) {
7552 return wuffs_crc32__ieee_hasher__set_quirk_enabled(this, a_quirk, a_enabled);
7553 }
7554
7555 inline uint32_t
7556 update_u32(
7557 wuffs_base__slice_u8 a_x) {
7558 return wuffs_crc32__ieee_hasher__update_u32(this, a_x);
7559 }
7560
7561#endif // __cplusplus
7562}; // struct wuffs_crc32__ieee_hasher__struct
7563
7564#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7565
Nigel Taofe9d08f2022-10-28 17:30:51 +11007566#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32) || defined(WUFFS_NONMONOLITHIC)
7567
7568#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) || defined(WUFFS_NONMONOLITHIC)
7569
Nigel Taoe360a532021-04-05 22:47:03 +10007570// ---------------- Status Codes
7571
7572extern const char wuffs_deflate__error__bad_huffman_code_over_subscribed[];
7573extern const char wuffs_deflate__error__bad_huffman_code_under_subscribed[];
7574extern const char wuffs_deflate__error__bad_huffman_code_length_count[];
7575extern const char wuffs_deflate__error__bad_huffman_code_length_repetition[];
7576extern const char wuffs_deflate__error__bad_huffman_code[];
7577extern const char wuffs_deflate__error__bad_huffman_minimum_code_length[];
7578extern const char wuffs_deflate__error__bad_block[];
7579extern const char wuffs_deflate__error__bad_distance[];
7580extern const char wuffs_deflate__error__bad_distance_code_count[];
7581extern const char wuffs_deflate__error__bad_literal_length_code_count[];
7582extern const char wuffs_deflate__error__inconsistent_stored_block_length[];
7583extern const char wuffs_deflate__error__missing_end_of_block_code[];
7584extern const char wuffs_deflate__error__no_huffman_codes[];
7585
7586// ---------------- Public Consts
7587
7588#define WUFFS_DEFLATE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
7589
7590// ---------------- Struct Declarations
7591
7592typedef struct wuffs_deflate__decoder__struct wuffs_deflate__decoder;
7593
7594#ifdef __cplusplus
7595extern "C" {
7596#endif
7597
7598// ---------------- Public Initializer Prototypes
7599
7600// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7601// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7602//
7603// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7604// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7605
7606wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7607wuffs_deflate__decoder__initialize(
7608 wuffs_deflate__decoder* self,
7609 size_t sizeof_star_self,
7610 uint64_t wuffs_version,
7611 uint32_t options);
7612
7613size_t
7614sizeof__wuffs_deflate__decoder();
7615
7616// ---------------- Allocs
7617
7618// These functions allocate and initialize Wuffs structs. They return NULL if
7619// memory allocation fails. If they return non-NULL, there is no need to call
7620// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7621// calling free on the returned pointer. That pointer is effectively a C++
7622// std::unique_ptr<T, decltype(&free)>.
7623
7624wuffs_deflate__decoder*
7625wuffs_deflate__decoder__alloc();
7626
7627static inline wuffs_base__io_transformer*
7628wuffs_deflate__decoder__alloc_as__wuffs_base__io_transformer() {
7629 return (wuffs_base__io_transformer*)(wuffs_deflate__decoder__alloc());
7630}
7631
7632// ---------------- Upcasts
7633
7634static inline wuffs_base__io_transformer*
7635wuffs_deflate__decoder__upcast_as__wuffs_base__io_transformer(
7636 wuffs_deflate__decoder* p) {
7637 return (wuffs_base__io_transformer*)p;
7638}
7639
7640// ---------------- Public Function Prototypes
7641
7642WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7643wuffs_deflate__decoder__add_history(
7644 wuffs_deflate__decoder* self,
7645 wuffs_base__slice_u8 a_hist);
7646
7647WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7648wuffs_deflate__decoder__set_quirk_enabled(
7649 wuffs_deflate__decoder* self,
7650 uint32_t a_quirk,
7651 bool a_enabled);
7652
7653WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7654wuffs_deflate__decoder__workbuf_len(
7655 const wuffs_deflate__decoder* self);
7656
7657WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7658wuffs_deflate__decoder__transform_io(
7659 wuffs_deflate__decoder* self,
7660 wuffs_base__io_buffer* a_dst,
7661 wuffs_base__io_buffer* a_src,
7662 wuffs_base__slice_u8 a_workbuf);
7663
7664#ifdef __cplusplus
7665} // extern "C"
7666#endif
7667
7668// ---------------- Struct Definitions
7669
7670// These structs' fields, and the sizeof them, are private implementation
7671// details that aren't guaranteed to be stable across Wuffs versions.
7672//
7673// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7674
7675#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7676
7677struct wuffs_deflate__decoder__struct {
7678 // Do not access the private_impl's or private_data's fields directly. There
7679 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7680 // the wuffs_foo__bar__baz functions.
7681 //
7682 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7683 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7684
7685 struct {
7686 uint32_t magic;
7687 uint32_t active_coroutine;
7688 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
7689 wuffs_base__vtable null_vtable;
7690
7691 uint32_t f_bits;
7692 uint32_t f_n_bits;
Nigel Taoc9d2ed72021-08-15 13:50:22 +10007693 uint64_t f_transformed_history_count;
Nigel Taoe360a532021-04-05 22:47:03 +10007694 uint32_t f_history_index;
7695 uint32_t f_n_huffs_bits[2];
7696 bool f_end_of_block;
7697
7698 uint32_t p_transform_io[1];
7699 uint32_t p_decode_blocks[1];
7700 uint32_t p_decode_uncompressed[1];
7701 uint32_t p_init_dynamic_huffman[1];
Nigel Tao5571bfe2021-06-24 22:44:29 +10007702 wuffs_base__status (*choosy_decode_huffman_fast64)(
7703 wuffs_deflate__decoder* self,
7704 wuffs_base__io_buffer* a_dst,
7705 wuffs_base__io_buffer* a_src);
Nigel Taoe360a532021-04-05 22:47:03 +10007706 uint32_t p_decode_huffman_slow[1];
7707 } private_impl;
7708
7709 struct {
7710 uint32_t f_huffs[2][1024];
7711 uint8_t f_history[33025];
7712 uint8_t f_code_lengths[320];
7713
7714 struct {
7715 uint32_t v_final;
7716 } s_decode_blocks[1];
7717 struct {
7718 uint32_t v_length;
7719 uint64_t scratch;
7720 } s_decode_uncompressed[1];
7721 struct {
7722 uint32_t v_bits;
7723 uint32_t v_n_bits;
7724 uint32_t v_n_lit;
7725 uint32_t v_n_dist;
7726 uint32_t v_n_clen;
7727 uint32_t v_i;
7728 uint32_t v_mask;
Nigel Taoe360a532021-04-05 22:47:03 +10007729 uint32_t v_n_extra_bits;
7730 uint8_t v_rep_symbol;
7731 uint32_t v_rep_count;
7732 } s_init_dynamic_huffman[1];
7733 struct {
7734 uint32_t v_bits;
7735 uint32_t v_n_bits;
Nigel Taoe360a532021-04-05 22:47:03 +10007736 uint32_t v_table_entry_n_bits;
7737 uint32_t v_lmask;
7738 uint32_t v_dmask;
7739 uint32_t v_redir_top;
7740 uint32_t v_redir_mask;
7741 uint32_t v_length;
7742 uint32_t v_dist_minus_1;
Nigel Taoe360a532021-04-05 22:47:03 +10007743 uint64_t scratch;
7744 } s_decode_huffman_slow[1];
7745 } private_data;
7746
7747#ifdef __cplusplus
7748#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7749 using unique_ptr = std::unique_ptr<wuffs_deflate__decoder, decltype(&free)>;
7750
7751 // On failure, the alloc_etc functions return nullptr. They don't throw.
7752
7753 static inline unique_ptr
7754 alloc() {
7755 return unique_ptr(wuffs_deflate__decoder__alloc(), &free);
7756 }
7757
7758 static inline wuffs_base__io_transformer::unique_ptr
7759 alloc_as__wuffs_base__io_transformer() {
7760 return wuffs_base__io_transformer::unique_ptr(
7761 wuffs_deflate__decoder__alloc_as__wuffs_base__io_transformer(), &free);
7762 }
7763#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7764
7765#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7766 // Disallow constructing or copying an object via standard C++ mechanisms,
7767 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
7768 // size and field layout is not part of the public, stable, memory-safe API.
7769 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
7770 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
7771 // their first argument) rather than tweaking bar.private_impl.qux fields.
7772 //
7773 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
7774 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
7775 // order to provide convenience methods. These forward on "this", so that you
7776 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
7777 wuffs_deflate__decoder__struct() = delete;
7778 wuffs_deflate__decoder__struct(const wuffs_deflate__decoder__struct&) = delete;
7779 wuffs_deflate__decoder__struct& operator=(
7780 const wuffs_deflate__decoder__struct&) = delete;
7781#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
7782
7783#if !defined(WUFFS_IMPLEMENTATION)
7784 // As above, the size of the struct is not part of the public API, and unless
7785 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
7786 // allocated, not stack allocated. Its size is not intended to be known at
7787 // compile time, but it is unfortunately divulged as a side effect of
7788 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
7789 // instead of "sizeof T", invoking the operator. To make the two values
7790 // different, so that passing the latter will be rejected by the initialize
7791 // function, we add an arbitrary amount of dead weight.
7792 uint8_t dead_weight[123000000]; // 123 MB.
7793#endif // !defined(WUFFS_IMPLEMENTATION)
7794
7795 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7796 initialize(
7797 size_t sizeof_star_self,
7798 uint64_t wuffs_version,
7799 uint32_t options) {
7800 return wuffs_deflate__decoder__initialize(
7801 this, sizeof_star_self, wuffs_version, options);
7802 }
7803
7804 inline wuffs_base__io_transformer*
7805 upcast_as__wuffs_base__io_transformer() {
7806 return (wuffs_base__io_transformer*)this;
7807 }
7808
7809 inline wuffs_base__empty_struct
7810 add_history(
7811 wuffs_base__slice_u8 a_hist) {
7812 return wuffs_deflate__decoder__add_history(this, a_hist);
7813 }
7814
7815 inline wuffs_base__empty_struct
7816 set_quirk_enabled(
7817 uint32_t a_quirk,
7818 bool a_enabled) {
7819 return wuffs_deflate__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
7820 }
7821
7822 inline wuffs_base__range_ii_u64
7823 workbuf_len() const {
7824 return wuffs_deflate__decoder__workbuf_len(this);
7825 }
7826
7827 inline wuffs_base__status
7828 transform_io(
7829 wuffs_base__io_buffer* a_dst,
7830 wuffs_base__io_buffer* a_src,
7831 wuffs_base__slice_u8 a_workbuf) {
7832 return wuffs_deflate__decoder__transform_io(this, a_dst, a_src, a_workbuf);
7833 }
7834
7835#endif // __cplusplus
7836}; // struct wuffs_deflate__decoder__struct
7837
7838#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7839
Nigel Taofe9d08f2022-10-28 17:30:51 +11007840#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE) || defined(WUFFS_NONMONOLITHIC)
7841
7842#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC)
7843
Nigel Taoe360a532021-04-05 22:47:03 +10007844// ---------------- Status Codes
7845
7846extern const char wuffs_lzw__error__bad_code[];
7847
7848// ---------------- Public Consts
7849
7850#define WUFFS_LZW__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
7851
7852// ---------------- Struct Declarations
7853
7854typedef struct wuffs_lzw__decoder__struct wuffs_lzw__decoder;
7855
7856#ifdef __cplusplus
7857extern "C" {
7858#endif
7859
7860// ---------------- Public Initializer Prototypes
7861
7862// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
7863// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
7864//
7865// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
7866// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
7867
7868wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
7869wuffs_lzw__decoder__initialize(
7870 wuffs_lzw__decoder* self,
7871 size_t sizeof_star_self,
7872 uint64_t wuffs_version,
7873 uint32_t options);
7874
7875size_t
7876sizeof__wuffs_lzw__decoder();
7877
7878// ---------------- Allocs
7879
7880// These functions allocate and initialize Wuffs structs. They return NULL if
7881// memory allocation fails. If they return non-NULL, there is no need to call
7882// wuffs_foo__bar__initialize, but the caller is responsible for eventually
7883// calling free on the returned pointer. That pointer is effectively a C++
7884// std::unique_ptr<T, decltype(&free)>.
7885
7886wuffs_lzw__decoder*
7887wuffs_lzw__decoder__alloc();
7888
7889static inline wuffs_base__io_transformer*
7890wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer() {
7891 return (wuffs_base__io_transformer*)(wuffs_lzw__decoder__alloc());
7892}
7893
7894// ---------------- Upcasts
7895
7896static inline wuffs_base__io_transformer*
7897wuffs_lzw__decoder__upcast_as__wuffs_base__io_transformer(
7898 wuffs_lzw__decoder* p) {
7899 return (wuffs_base__io_transformer*)p;
7900}
7901
7902// ---------------- Public Function Prototypes
7903
7904WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7905wuffs_lzw__decoder__set_quirk_enabled(
7906 wuffs_lzw__decoder* self,
7907 uint32_t a_quirk,
7908 bool a_enabled);
7909
7910WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
7911wuffs_lzw__decoder__set_literal_width(
7912 wuffs_lzw__decoder* self,
7913 uint32_t a_lw);
7914
7915WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
7916wuffs_lzw__decoder__workbuf_len(
7917 const wuffs_lzw__decoder* self);
7918
7919WUFFS_BASE__MAYBE_STATIC wuffs_base__status
7920wuffs_lzw__decoder__transform_io(
7921 wuffs_lzw__decoder* self,
7922 wuffs_base__io_buffer* a_dst,
7923 wuffs_base__io_buffer* a_src,
7924 wuffs_base__slice_u8 a_workbuf);
7925
7926WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8
7927wuffs_lzw__decoder__flush(
7928 wuffs_lzw__decoder* self);
7929
7930#ifdef __cplusplus
7931} // extern "C"
7932#endif
7933
7934// ---------------- Struct Definitions
7935
7936// These structs' fields, and the sizeof them, are private implementation
7937// details that aren't guaranteed to be stable across Wuffs versions.
7938//
7939// See https://en.wikipedia.org/wiki/Opaque_pointer#C
7940
7941#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
7942
7943struct wuffs_lzw__decoder__struct {
7944 // Do not access the private_impl's or private_data's fields directly. There
7945 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
7946 // the wuffs_foo__bar__baz functions.
7947 //
7948 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
7949 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
7950
7951 struct {
7952 uint32_t magic;
7953 uint32_t active_coroutine;
7954 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
7955 wuffs_base__vtable null_vtable;
7956
7957 uint32_t f_set_literal_width_arg;
7958 uint32_t f_literal_width;
7959 uint32_t f_clear_code;
7960 uint32_t f_end_code;
7961 uint32_t f_save_code;
7962 uint32_t f_prev_code;
7963 uint32_t f_width;
7964 uint32_t f_bits;
7965 uint32_t f_n_bits;
7966 uint32_t f_output_ri;
7967 uint32_t f_output_wi;
7968 uint32_t f_read_from_return_value;
7969 uint16_t f_prefixes[4096];
7970
7971 uint32_t p_transform_io[1];
7972 uint32_t p_write_to[1];
7973 } private_impl;
7974
7975 struct {
7976 uint8_t f_suffixes[4096][8];
7977 uint16_t f_lm1s[4096];
7978 uint8_t f_output[8199];
7979 } private_data;
7980
7981#ifdef __cplusplus
7982#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7983 using unique_ptr = std::unique_ptr<wuffs_lzw__decoder, decltype(&free)>;
7984
7985 // On failure, the alloc_etc functions return nullptr. They don't throw.
7986
7987 static inline unique_ptr
7988 alloc() {
7989 return unique_ptr(wuffs_lzw__decoder__alloc(), &free);
7990 }
7991
7992 static inline wuffs_base__io_transformer::unique_ptr
7993 alloc_as__wuffs_base__io_transformer() {
7994 return wuffs_base__io_transformer::unique_ptr(
7995 wuffs_lzw__decoder__alloc_as__wuffs_base__io_transformer(), &free);
7996 }
7997#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
7998
7999#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8000 // Disallow constructing or copying an object via standard C++ mechanisms,
8001 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8002 // size and field layout is not part of the public, stable, memory-safe API.
8003 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8004 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8005 // their first argument) rather than tweaking bar.private_impl.qux fields.
8006 //
8007 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8008 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8009 // order to provide convenience methods. These forward on "this", so that you
8010 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8011 wuffs_lzw__decoder__struct() = delete;
8012 wuffs_lzw__decoder__struct(const wuffs_lzw__decoder__struct&) = delete;
8013 wuffs_lzw__decoder__struct& operator=(
8014 const wuffs_lzw__decoder__struct&) = delete;
8015#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8016
8017#if !defined(WUFFS_IMPLEMENTATION)
8018 // As above, the size of the struct is not part of the public API, and unless
8019 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8020 // allocated, not stack allocated. Its size is not intended to be known at
8021 // compile time, but it is unfortunately divulged as a side effect of
8022 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8023 // instead of "sizeof T", invoking the operator. To make the two values
8024 // different, so that passing the latter will be rejected by the initialize
8025 // function, we add an arbitrary amount of dead weight.
8026 uint8_t dead_weight[123000000]; // 123 MB.
8027#endif // !defined(WUFFS_IMPLEMENTATION)
8028
8029 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8030 initialize(
8031 size_t sizeof_star_self,
8032 uint64_t wuffs_version,
8033 uint32_t options) {
8034 return wuffs_lzw__decoder__initialize(
8035 this, sizeof_star_self, wuffs_version, options);
8036 }
8037
8038 inline wuffs_base__io_transformer*
8039 upcast_as__wuffs_base__io_transformer() {
8040 return (wuffs_base__io_transformer*)this;
8041 }
8042
8043 inline wuffs_base__empty_struct
8044 set_quirk_enabled(
8045 uint32_t a_quirk,
8046 bool a_enabled) {
8047 return wuffs_lzw__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8048 }
8049
8050 inline wuffs_base__empty_struct
8051 set_literal_width(
8052 uint32_t a_lw) {
8053 return wuffs_lzw__decoder__set_literal_width(this, a_lw);
8054 }
8055
8056 inline wuffs_base__range_ii_u64
8057 workbuf_len() const {
8058 return wuffs_lzw__decoder__workbuf_len(this);
8059 }
8060
8061 inline wuffs_base__status
8062 transform_io(
8063 wuffs_base__io_buffer* a_dst,
8064 wuffs_base__io_buffer* a_src,
8065 wuffs_base__slice_u8 a_workbuf) {
8066 return wuffs_lzw__decoder__transform_io(this, a_dst, a_src, a_workbuf);
8067 }
8068
8069 inline wuffs_base__slice_u8
8070 flush() {
8071 return wuffs_lzw__decoder__flush(this);
8072 }
8073
8074#endif // __cplusplus
8075}; // struct wuffs_lzw__decoder__struct
8076
8077#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8078
Nigel Taofe9d08f2022-10-28 17:30:51 +11008079#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW) || defined(WUFFS_NONMONOLITHIC)
8080
8081#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) || defined(WUFFS_NONMONOLITHIC)
8082
Nigel Taoe360a532021-04-05 22:47:03 +10008083// ---------------- Status Codes
8084
8085extern const char wuffs_gif__error__bad_extension_label[];
8086extern const char wuffs_gif__error__bad_frame_size[];
8087extern const char wuffs_gif__error__bad_graphic_control[];
8088extern const char wuffs_gif__error__bad_header[];
8089extern const char wuffs_gif__error__bad_literal_width[];
8090extern const char wuffs_gif__error__bad_palette[];
8091
8092// ---------------- Public Consts
8093
8094#define WUFFS_GIF__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
8095
8096#define WUFFS_GIF__QUIRK_DELAY_NUM_DECODED_FRAMES 1041635328
8097
8098#define WUFFS_GIF__QUIRK_FIRST_FRAME_LOCAL_PALETTE_MEANS_BLACK_BACKGROUND 1041635329
8099
8100#define WUFFS_GIF__QUIRK_HONOR_BACKGROUND_COLOR 1041635330
8101
8102#define WUFFS_GIF__QUIRK_IGNORE_TOO_MUCH_PIXEL_DATA 1041635331
8103
8104#define WUFFS_GIF__QUIRK_IMAGE_BOUNDS_ARE_STRICT 1041635332
8105
8106#define WUFFS_GIF__QUIRK_REJECT_EMPTY_FRAME 1041635333
8107
8108#define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635334
8109
8110// ---------------- Struct Declarations
8111
8112typedef struct wuffs_gif__decoder__struct wuffs_gif__decoder;
8113
8114#ifdef __cplusplus
8115extern "C" {
8116#endif
8117
8118// ---------------- Public Initializer Prototypes
8119
8120// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8121// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8122//
8123// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8124// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8125
8126wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8127wuffs_gif__decoder__initialize(
8128 wuffs_gif__decoder* self,
8129 size_t sizeof_star_self,
8130 uint64_t wuffs_version,
8131 uint32_t options);
8132
8133size_t
8134sizeof__wuffs_gif__decoder();
8135
8136// ---------------- Allocs
8137
8138// These functions allocate and initialize Wuffs structs. They return NULL if
8139// memory allocation fails. If they return non-NULL, there is no need to call
8140// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8141// calling free on the returned pointer. That pointer is effectively a C++
8142// std::unique_ptr<T, decltype(&free)>.
8143
8144wuffs_gif__decoder*
8145wuffs_gif__decoder__alloc();
8146
8147static inline wuffs_base__image_decoder*
8148wuffs_gif__decoder__alloc_as__wuffs_base__image_decoder() {
8149 return (wuffs_base__image_decoder*)(wuffs_gif__decoder__alloc());
8150}
8151
8152// ---------------- Upcasts
8153
8154static inline wuffs_base__image_decoder*
8155wuffs_gif__decoder__upcast_as__wuffs_base__image_decoder(
8156 wuffs_gif__decoder* p) {
8157 return (wuffs_base__image_decoder*)p;
8158}
8159
8160// ---------------- Public Function Prototypes
8161
8162WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8163wuffs_gif__decoder__set_quirk_enabled(
8164 wuffs_gif__decoder* self,
8165 uint32_t a_quirk,
8166 bool a_enabled);
8167
8168WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8169wuffs_gif__decoder__decode_image_config(
8170 wuffs_gif__decoder* self,
8171 wuffs_base__image_config* a_dst,
8172 wuffs_base__io_buffer* a_src);
8173
8174WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8175wuffs_gif__decoder__set_report_metadata(
8176 wuffs_gif__decoder* self,
8177 uint32_t a_fourcc,
8178 bool a_report);
8179
8180WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8181wuffs_gif__decoder__tell_me_more(
8182 wuffs_gif__decoder* self,
8183 wuffs_base__io_buffer* a_dst,
8184 wuffs_base__more_information* a_minfo,
8185 wuffs_base__io_buffer* a_src);
8186
8187WUFFS_BASE__MAYBE_STATIC uint32_t
8188wuffs_gif__decoder__num_animation_loops(
8189 const wuffs_gif__decoder* self);
8190
8191WUFFS_BASE__MAYBE_STATIC uint64_t
8192wuffs_gif__decoder__num_decoded_frame_configs(
8193 const wuffs_gif__decoder* self);
8194
8195WUFFS_BASE__MAYBE_STATIC uint64_t
8196wuffs_gif__decoder__num_decoded_frames(
8197 const wuffs_gif__decoder* self);
8198
8199WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
8200wuffs_gif__decoder__frame_dirty_rect(
8201 const wuffs_gif__decoder* self);
8202
8203WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8204wuffs_gif__decoder__workbuf_len(
8205 const wuffs_gif__decoder* self);
8206
8207WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8208wuffs_gif__decoder__restart_frame(
8209 wuffs_gif__decoder* self,
8210 uint64_t a_index,
8211 uint64_t a_io_position);
8212
8213WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8214wuffs_gif__decoder__decode_frame_config(
8215 wuffs_gif__decoder* self,
8216 wuffs_base__frame_config* a_dst,
8217 wuffs_base__io_buffer* a_src);
8218
8219WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8220wuffs_gif__decoder__decode_frame(
8221 wuffs_gif__decoder* self,
8222 wuffs_base__pixel_buffer* a_dst,
8223 wuffs_base__io_buffer* a_src,
8224 wuffs_base__pixel_blend a_blend,
8225 wuffs_base__slice_u8 a_workbuf,
8226 wuffs_base__decode_frame_options* a_opts);
8227
8228#ifdef __cplusplus
8229} // extern "C"
8230#endif
8231
8232// ---------------- Struct Definitions
8233
8234// These structs' fields, and the sizeof them, are private implementation
8235// details that aren't guaranteed to be stable across Wuffs versions.
8236//
8237// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8238
8239#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8240
8241struct wuffs_gif__decoder__struct {
8242 // Do not access the private_impl's or private_data's fields directly. There
8243 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8244 // the wuffs_foo__bar__baz functions.
8245 //
8246 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8247 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8248
8249 struct {
8250 uint32_t magic;
8251 uint32_t active_coroutine;
8252 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
8253 wuffs_base__vtable null_vtable;
8254
8255 uint32_t f_width;
8256 uint32_t f_height;
8257 uint8_t f_call_sequence;
Nigel Taoe360a532021-04-05 22:47:03 +10008258 bool f_report_metadata_iccp;
8259 bool f_report_metadata_xmp;
8260 uint32_t f_metadata_fourcc;
8261 uint64_t f_metadata_io_position;
8262 bool f_quirks[7];
8263 bool f_delayed_num_decoded_frames;
Nigel Taoe360a532021-04-05 22:47:03 +10008264 bool f_previous_lzw_decode_ended_abruptly;
Nigel Tao123a5c62022-06-03 14:17:20 +10008265 bool f_seen_header;
Nigel Taoe360a532021-04-05 22:47:03 +10008266 bool f_has_global_palette;
8267 uint8_t f_interlace;
Nigel Taobf9dab32021-11-18 19:19:55 +11008268 bool f_seen_num_animation_loops_value;
8269 uint32_t f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +10008270 uint32_t f_background_color_u32_argb_premul;
8271 uint32_t f_black_color_u32_argb_premul;
8272 bool f_gc_has_transparent_index;
8273 uint8_t f_gc_transparent_index;
8274 uint8_t f_gc_disposal;
8275 uint64_t f_gc_duration;
8276 uint64_t f_frame_config_io_position;
8277 uint64_t f_num_decoded_frame_configs_value;
8278 uint64_t f_num_decoded_frames_value;
8279 uint32_t f_frame_rect_x0;
8280 uint32_t f_frame_rect_y0;
8281 uint32_t f_frame_rect_x1;
8282 uint32_t f_frame_rect_y1;
8283 uint32_t f_dst_x;
8284 uint32_t f_dst_y;
8285 uint32_t f_dirty_max_excl_y;
8286 uint64_t f_compressed_ri;
8287 uint64_t f_compressed_wi;
8288 wuffs_base__pixel_swizzler f_swizzler;
8289
8290 uint32_t p_decode_image_config[1];
8291 uint32_t p_tell_me_more[1];
8292 uint32_t p_decode_frame_config[1];
8293 uint32_t p_skip_frame[1];
8294 uint32_t p_decode_frame[1];
8295 uint32_t p_decode_up_to_id_part1[1];
8296 uint32_t p_decode_header[1];
8297 uint32_t p_decode_lsd[1];
8298 uint32_t p_decode_extension[1];
8299 uint32_t p_skip_blocks[1];
8300 uint32_t p_decode_ae[1];
8301 uint32_t p_decode_gc[1];
8302 uint32_t p_decode_id_part0[1];
8303 uint32_t p_decode_id_part1[1];
8304 uint32_t p_decode_id_part2[1];
8305 } private_impl;
8306
8307 struct {
8308 uint8_t f_compressed[4096];
8309 uint8_t f_palettes[2][1024];
8310 uint8_t f_dst_palette[1024];
8311 wuffs_lzw__decoder f_lzw;
8312
8313 struct {
8314 uint32_t v_background_color;
8315 } s_decode_frame_config[1];
8316 struct {
8317 uint64_t scratch;
8318 } s_skip_frame[1];
8319 struct {
8320 uint8_t v_c[6];
8321 uint32_t v_i;
8322 } s_decode_header[1];
8323 struct {
8324 uint8_t v_flags;
8325 uint8_t v_background_color_index;
8326 uint32_t v_num_palette_entries;
8327 uint32_t v_i;
8328 uint64_t scratch;
8329 } s_decode_lsd[1];
8330 struct {
8331 uint64_t scratch;
8332 } s_skip_blocks[1];
8333 struct {
8334 uint8_t v_block_size;
8335 bool v_is_animexts;
8336 bool v_is_netscape;
8337 bool v_is_iccp;
8338 bool v_is_xmp;
8339 uint64_t scratch;
8340 } s_decode_ae[1];
8341 struct {
8342 uint64_t scratch;
8343 } s_decode_gc[1];
8344 struct {
8345 uint64_t scratch;
8346 } s_decode_id_part0[1];
8347 struct {
8348 uint8_t v_which_palette;
8349 uint32_t v_num_palette_entries;
8350 uint32_t v_i;
8351 uint64_t scratch;
8352 } s_decode_id_part1[1];
8353 struct {
8354 uint64_t v_block_size;
8355 bool v_need_block_size;
Nigel Taoe360a532021-04-05 22:47:03 +10008356 uint64_t scratch;
8357 } s_decode_id_part2[1];
8358 } private_data;
8359
8360#ifdef __cplusplus
8361#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8362 using unique_ptr = std::unique_ptr<wuffs_gif__decoder, decltype(&free)>;
8363
8364 // On failure, the alloc_etc functions return nullptr. They don't throw.
8365
8366 static inline unique_ptr
8367 alloc() {
8368 return unique_ptr(wuffs_gif__decoder__alloc(), &free);
8369 }
8370
8371 static inline wuffs_base__image_decoder::unique_ptr
8372 alloc_as__wuffs_base__image_decoder() {
8373 return wuffs_base__image_decoder::unique_ptr(
8374 wuffs_gif__decoder__alloc_as__wuffs_base__image_decoder(), &free);
8375 }
8376#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8377
8378#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8379 // Disallow constructing or copying an object via standard C++ mechanisms,
8380 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8381 // size and field layout is not part of the public, stable, memory-safe API.
8382 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8383 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8384 // their first argument) rather than tweaking bar.private_impl.qux fields.
8385 //
8386 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8387 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8388 // order to provide convenience methods. These forward on "this", so that you
8389 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8390 wuffs_gif__decoder__struct() = delete;
8391 wuffs_gif__decoder__struct(const wuffs_gif__decoder__struct&) = delete;
8392 wuffs_gif__decoder__struct& operator=(
8393 const wuffs_gif__decoder__struct&) = delete;
8394#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8395
8396#if !defined(WUFFS_IMPLEMENTATION)
8397 // As above, the size of the struct is not part of the public API, and unless
8398 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8399 // allocated, not stack allocated. Its size is not intended to be known at
8400 // compile time, but it is unfortunately divulged as a side effect of
8401 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8402 // instead of "sizeof T", invoking the operator. To make the two values
8403 // different, so that passing the latter will be rejected by the initialize
8404 // function, we add an arbitrary amount of dead weight.
8405 uint8_t dead_weight[123000000]; // 123 MB.
8406#endif // !defined(WUFFS_IMPLEMENTATION)
8407
8408 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8409 initialize(
8410 size_t sizeof_star_self,
8411 uint64_t wuffs_version,
8412 uint32_t options) {
8413 return wuffs_gif__decoder__initialize(
8414 this, sizeof_star_self, wuffs_version, options);
8415 }
8416
8417 inline wuffs_base__image_decoder*
8418 upcast_as__wuffs_base__image_decoder() {
8419 return (wuffs_base__image_decoder*)this;
8420 }
8421
8422 inline wuffs_base__empty_struct
8423 set_quirk_enabled(
8424 uint32_t a_quirk,
8425 bool a_enabled) {
8426 return wuffs_gif__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8427 }
8428
8429 inline wuffs_base__status
8430 decode_image_config(
8431 wuffs_base__image_config* a_dst,
8432 wuffs_base__io_buffer* a_src) {
8433 return wuffs_gif__decoder__decode_image_config(this, a_dst, a_src);
8434 }
8435
8436 inline wuffs_base__empty_struct
8437 set_report_metadata(
8438 uint32_t a_fourcc,
8439 bool a_report) {
8440 return wuffs_gif__decoder__set_report_metadata(this, a_fourcc, a_report);
8441 }
8442
8443 inline wuffs_base__status
8444 tell_me_more(
8445 wuffs_base__io_buffer* a_dst,
8446 wuffs_base__more_information* a_minfo,
8447 wuffs_base__io_buffer* a_src) {
8448 return wuffs_gif__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
8449 }
8450
8451 inline uint32_t
8452 num_animation_loops() const {
8453 return wuffs_gif__decoder__num_animation_loops(this);
8454 }
8455
8456 inline uint64_t
8457 num_decoded_frame_configs() const {
8458 return wuffs_gif__decoder__num_decoded_frame_configs(this);
8459 }
8460
8461 inline uint64_t
8462 num_decoded_frames() const {
8463 return wuffs_gif__decoder__num_decoded_frames(this);
8464 }
8465
8466 inline wuffs_base__rect_ie_u32
8467 frame_dirty_rect() const {
8468 return wuffs_gif__decoder__frame_dirty_rect(this);
8469 }
8470
8471 inline wuffs_base__range_ii_u64
8472 workbuf_len() const {
8473 return wuffs_gif__decoder__workbuf_len(this);
8474 }
8475
8476 inline wuffs_base__status
8477 restart_frame(
8478 uint64_t a_index,
8479 uint64_t a_io_position) {
8480 return wuffs_gif__decoder__restart_frame(this, a_index, a_io_position);
8481 }
8482
8483 inline wuffs_base__status
8484 decode_frame_config(
8485 wuffs_base__frame_config* a_dst,
8486 wuffs_base__io_buffer* a_src) {
8487 return wuffs_gif__decoder__decode_frame_config(this, a_dst, a_src);
8488 }
8489
8490 inline wuffs_base__status
8491 decode_frame(
8492 wuffs_base__pixel_buffer* a_dst,
8493 wuffs_base__io_buffer* a_src,
8494 wuffs_base__pixel_blend a_blend,
8495 wuffs_base__slice_u8 a_workbuf,
8496 wuffs_base__decode_frame_options* a_opts) {
8497 return wuffs_gif__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
8498 }
8499
8500#endif // __cplusplus
8501}; // struct wuffs_gif__decoder__struct
8502
8503#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8504
Nigel Taofe9d08f2022-10-28 17:30:51 +11008505#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF) || defined(WUFFS_NONMONOLITHIC)
8506
8507#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) || defined(WUFFS_NONMONOLITHIC)
8508
Nigel Taoe360a532021-04-05 22:47:03 +10008509// ---------------- Status Codes
8510
8511extern const char wuffs_gzip__error__bad_checksum[];
8512extern const char wuffs_gzip__error__bad_compression_method[];
8513extern const char wuffs_gzip__error__bad_encoding_flags[];
8514extern const char wuffs_gzip__error__bad_header[];
8515
8516// ---------------- Public Consts
8517
8518#define WUFFS_GZIP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
8519
8520// ---------------- Struct Declarations
8521
8522typedef struct wuffs_gzip__decoder__struct wuffs_gzip__decoder;
8523
8524#ifdef __cplusplus
8525extern "C" {
8526#endif
8527
8528// ---------------- Public Initializer Prototypes
8529
8530// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8531// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8532//
8533// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8534// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8535
8536wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8537wuffs_gzip__decoder__initialize(
8538 wuffs_gzip__decoder* self,
8539 size_t sizeof_star_self,
8540 uint64_t wuffs_version,
8541 uint32_t options);
8542
8543size_t
8544sizeof__wuffs_gzip__decoder();
8545
8546// ---------------- Allocs
8547
8548// These functions allocate and initialize Wuffs structs. They return NULL if
8549// memory allocation fails. If they return non-NULL, there is no need to call
8550// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8551// calling free on the returned pointer. That pointer is effectively a C++
8552// std::unique_ptr<T, decltype(&free)>.
8553
8554wuffs_gzip__decoder*
8555wuffs_gzip__decoder__alloc();
8556
8557static inline wuffs_base__io_transformer*
8558wuffs_gzip__decoder__alloc_as__wuffs_base__io_transformer() {
8559 return (wuffs_base__io_transformer*)(wuffs_gzip__decoder__alloc());
8560}
8561
8562// ---------------- Upcasts
8563
8564static inline wuffs_base__io_transformer*
8565wuffs_gzip__decoder__upcast_as__wuffs_base__io_transformer(
8566 wuffs_gzip__decoder* p) {
8567 return (wuffs_base__io_transformer*)p;
8568}
8569
8570// ---------------- Public Function Prototypes
8571
8572WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8573wuffs_gzip__decoder__set_quirk_enabled(
8574 wuffs_gzip__decoder* self,
8575 uint32_t a_quirk,
8576 bool a_enabled);
8577
8578WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8579wuffs_gzip__decoder__workbuf_len(
8580 const wuffs_gzip__decoder* self);
8581
8582WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8583wuffs_gzip__decoder__transform_io(
8584 wuffs_gzip__decoder* self,
8585 wuffs_base__io_buffer* a_dst,
8586 wuffs_base__io_buffer* a_src,
8587 wuffs_base__slice_u8 a_workbuf);
8588
8589#ifdef __cplusplus
8590} // extern "C"
8591#endif
8592
8593// ---------------- Struct Definitions
8594
8595// These structs' fields, and the sizeof them, are private implementation
8596// details that aren't guaranteed to be stable across Wuffs versions.
8597//
8598// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8599
8600#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8601
8602struct wuffs_gzip__decoder__struct {
8603 // Do not access the private_impl's or private_data's fields directly. There
8604 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8605 // the wuffs_foo__bar__baz functions.
8606 //
8607 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8608 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8609
8610 struct {
8611 uint32_t magic;
8612 uint32_t active_coroutine;
8613 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
8614 wuffs_base__vtable null_vtable;
8615
8616 bool f_ignore_checksum;
8617
8618 uint32_t p_transform_io[1];
8619 } private_impl;
8620
8621 struct {
8622 wuffs_crc32__ieee_hasher f_checksum;
8623 wuffs_deflate__decoder f_flate;
8624
8625 struct {
8626 uint8_t v_flags;
8627 uint32_t v_checksum_got;
8628 uint32_t v_decoded_length_got;
8629 uint32_t v_checksum_want;
8630 uint64_t scratch;
8631 } s_transform_io[1];
8632 } private_data;
8633
8634#ifdef __cplusplus
8635#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8636 using unique_ptr = std::unique_ptr<wuffs_gzip__decoder, decltype(&free)>;
8637
8638 // On failure, the alloc_etc functions return nullptr. They don't throw.
8639
8640 static inline unique_ptr
8641 alloc() {
8642 return unique_ptr(wuffs_gzip__decoder__alloc(), &free);
8643 }
8644
8645 static inline wuffs_base__io_transformer::unique_ptr
8646 alloc_as__wuffs_base__io_transformer() {
8647 return wuffs_base__io_transformer::unique_ptr(
8648 wuffs_gzip__decoder__alloc_as__wuffs_base__io_transformer(), &free);
8649 }
8650#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8651
8652#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8653 // Disallow constructing or copying an object via standard C++ mechanisms,
8654 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8655 // size and field layout is not part of the public, stable, memory-safe API.
8656 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8657 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8658 // their first argument) rather than tweaking bar.private_impl.qux fields.
8659 //
8660 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8661 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8662 // order to provide convenience methods. These forward on "this", so that you
8663 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8664 wuffs_gzip__decoder__struct() = delete;
8665 wuffs_gzip__decoder__struct(const wuffs_gzip__decoder__struct&) = delete;
8666 wuffs_gzip__decoder__struct& operator=(
8667 const wuffs_gzip__decoder__struct&) = delete;
8668#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8669
8670#if !defined(WUFFS_IMPLEMENTATION)
8671 // As above, the size of the struct is not part of the public API, and unless
8672 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8673 // allocated, not stack allocated. Its size is not intended to be known at
8674 // compile time, but it is unfortunately divulged as a side effect of
8675 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8676 // instead of "sizeof T", invoking the operator. To make the two values
8677 // different, so that passing the latter will be rejected by the initialize
8678 // function, we add an arbitrary amount of dead weight.
8679 uint8_t dead_weight[123000000]; // 123 MB.
8680#endif // !defined(WUFFS_IMPLEMENTATION)
8681
8682 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8683 initialize(
8684 size_t sizeof_star_self,
8685 uint64_t wuffs_version,
8686 uint32_t options) {
8687 return wuffs_gzip__decoder__initialize(
8688 this, sizeof_star_self, wuffs_version, options);
8689 }
8690
8691 inline wuffs_base__io_transformer*
8692 upcast_as__wuffs_base__io_transformer() {
8693 return (wuffs_base__io_transformer*)this;
8694 }
8695
8696 inline wuffs_base__empty_struct
8697 set_quirk_enabled(
8698 uint32_t a_quirk,
8699 bool a_enabled) {
8700 return wuffs_gzip__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8701 }
8702
8703 inline wuffs_base__range_ii_u64
8704 workbuf_len() const {
8705 return wuffs_gzip__decoder__workbuf_len(this);
8706 }
8707
8708 inline wuffs_base__status
8709 transform_io(
8710 wuffs_base__io_buffer* a_dst,
8711 wuffs_base__io_buffer* a_src,
8712 wuffs_base__slice_u8 a_workbuf) {
8713 return wuffs_gzip__decoder__transform_io(this, a_dst, a_src, a_workbuf);
8714 }
8715
8716#endif // __cplusplus
8717}; // struct wuffs_gzip__decoder__struct
8718
8719#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8720
Nigel Taofe9d08f2022-10-28 17:30:51 +11008721#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP) || defined(WUFFS_NONMONOLITHIC)
8722
8723#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) || defined(WUFFS_NONMONOLITHIC)
8724
Nigel Taoe360a532021-04-05 22:47:03 +10008725// ---------------- Status Codes
8726
8727extern const char wuffs_json__error__bad_c0_control_code[];
8728extern const char wuffs_json__error__bad_utf_8[];
8729extern const char wuffs_json__error__bad_backslash_escape[];
8730extern const char wuffs_json__error__bad_input[];
8731extern const char wuffs_json__error__bad_new_line_in_a_string[];
8732extern const char wuffs_json__error__bad_quirk_combination[];
8733extern const char wuffs_json__error__unsupported_number_length[];
8734extern const char wuffs_json__error__unsupported_recursion_depth[];
8735
8736// ---------------- Public Consts
8737
8738#define WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
8739
8740#define WUFFS_JSON__DECODER_DEPTH_MAX_INCL 1024
8741
8742#define WUFFS_JSON__DECODER_DST_TOKEN_BUFFER_LENGTH_MIN_INCL 1
8743
8744#define WUFFS_JSON__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 100
8745
8746#define WUFFS_JSON__QUIRK_ALLOW_ASCII_CONTROL_CODES 1225364480
8747
8748#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_A 1225364481
8749
8750#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_CAPITAL_U 1225364482
8751
8752#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_E 1225364483
8753
8754#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_NEW_LINE 1225364484
8755
8756#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_QUESTION_MARK 1225364485
8757
8758#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_SINGLE_QUOTE 1225364486
8759
8760#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_V 1225364487
8761
8762#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_X_AS_CODE_POINTS 1225364489
8763
8764#define WUFFS_JSON__QUIRK_ALLOW_BACKSLASH_ZERO 1225364490
8765
8766#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_BLOCK 1225364491
8767
8768#define WUFFS_JSON__QUIRK_ALLOW_COMMENT_LINE 1225364492
8769
8770#define WUFFS_JSON__QUIRK_ALLOW_EXTRA_COMMA 1225364493
8771
8772#define WUFFS_JSON__QUIRK_ALLOW_INF_NAN_NUMBERS 1225364494
8773
8774#define WUFFS_JSON__QUIRK_ALLOW_LEADING_ASCII_RECORD_SEPARATOR 1225364495
8775
8776#define WUFFS_JSON__QUIRK_ALLOW_LEADING_UNICODE_BYTE_ORDER_MARK 1225364496
8777
8778#define WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER 1225364497
8779
8780#define WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF 1225364498
8781
8782#define WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T 1225364499
8783
8784#define WUFFS_JSON__QUIRK_REPLACE_INVALID_UNICODE 1225364500
8785
8786// ---------------- Struct Declarations
8787
8788typedef struct wuffs_json__decoder__struct wuffs_json__decoder;
8789
8790#ifdef __cplusplus
8791extern "C" {
8792#endif
8793
8794// ---------------- Public Initializer Prototypes
8795
8796// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
8797// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
8798//
8799// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
8800// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
8801
8802wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8803wuffs_json__decoder__initialize(
8804 wuffs_json__decoder* self,
8805 size_t sizeof_star_self,
8806 uint64_t wuffs_version,
8807 uint32_t options);
8808
8809size_t
8810sizeof__wuffs_json__decoder();
8811
8812// ---------------- Allocs
8813
8814// These functions allocate and initialize Wuffs structs. They return NULL if
8815// memory allocation fails. If they return non-NULL, there is no need to call
8816// wuffs_foo__bar__initialize, but the caller is responsible for eventually
8817// calling free on the returned pointer. That pointer is effectively a C++
8818// std::unique_ptr<T, decltype(&free)>.
8819
8820wuffs_json__decoder*
8821wuffs_json__decoder__alloc();
8822
8823static inline wuffs_base__token_decoder*
8824wuffs_json__decoder__alloc_as__wuffs_base__token_decoder() {
8825 return (wuffs_base__token_decoder*)(wuffs_json__decoder__alloc());
8826}
8827
8828// ---------------- Upcasts
8829
8830static inline wuffs_base__token_decoder*
8831wuffs_json__decoder__upcast_as__wuffs_base__token_decoder(
8832 wuffs_json__decoder* p) {
8833 return (wuffs_base__token_decoder*)p;
8834}
8835
8836// ---------------- Public Function Prototypes
8837
8838WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
8839wuffs_json__decoder__set_quirk_enabled(
8840 wuffs_json__decoder* self,
8841 uint32_t a_quirk,
8842 bool a_enabled);
8843
8844WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
8845wuffs_json__decoder__workbuf_len(
8846 const wuffs_json__decoder* self);
8847
8848WUFFS_BASE__MAYBE_STATIC wuffs_base__status
8849wuffs_json__decoder__decode_tokens(
8850 wuffs_json__decoder* self,
8851 wuffs_base__token_buffer* a_dst,
8852 wuffs_base__io_buffer* a_src,
8853 wuffs_base__slice_u8 a_workbuf);
8854
8855#ifdef __cplusplus
8856} // extern "C"
8857#endif
8858
8859// ---------------- Struct Definitions
8860
8861// These structs' fields, and the sizeof them, are private implementation
8862// details that aren't guaranteed to be stable across Wuffs versions.
8863//
8864// See https://en.wikipedia.org/wiki/Opaque_pointer#C
8865
8866#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8867
8868struct wuffs_json__decoder__struct {
8869 // Do not access the private_impl's or private_data's fields directly. There
8870 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
8871 // the wuffs_foo__bar__baz functions.
8872 //
8873 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
8874 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
8875
8876 struct {
8877 uint32_t magic;
8878 uint32_t active_coroutine;
8879 wuffs_base__vtable vtable_for__wuffs_base__token_decoder;
8880 wuffs_base__vtable null_vtable;
8881
8882 bool f_quirks[21];
8883 bool f_allow_leading_ars;
8884 bool f_allow_leading_ubom;
8885 bool f_end_of_data;
8886 uint8_t f_trailer_stop;
8887 uint8_t f_comment_type;
8888
8889 uint32_t p_decode_tokens[1];
8890 uint32_t p_decode_leading[1];
8891 uint32_t p_decode_comment[1];
8892 uint32_t p_decode_inf_nan[1];
8893 uint32_t p_decode_trailer[1];
8894 } private_impl;
8895
8896 struct {
8897 uint32_t f_stack[32];
8898
8899 struct {
8900 uint32_t v_depth;
8901 uint32_t v_expect;
8902 uint32_t v_expect_after_value;
8903 } s_decode_tokens[1];
Nigel Taoe360a532021-04-05 22:47:03 +10008904 } private_data;
8905
8906#ifdef __cplusplus
8907#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8908 using unique_ptr = std::unique_ptr<wuffs_json__decoder, decltype(&free)>;
8909
8910 // On failure, the alloc_etc functions return nullptr. They don't throw.
8911
8912 static inline unique_ptr
8913 alloc() {
8914 return unique_ptr(wuffs_json__decoder__alloc(), &free);
8915 }
8916
8917 static inline wuffs_base__token_decoder::unique_ptr
8918 alloc_as__wuffs_base__token_decoder() {
8919 return wuffs_base__token_decoder::unique_ptr(
8920 wuffs_json__decoder__alloc_as__wuffs_base__token_decoder(), &free);
8921 }
8922#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
8923
8924#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8925 // Disallow constructing or copying an object via standard C++ mechanisms,
8926 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
8927 // size and field layout is not part of the public, stable, memory-safe API.
8928 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
8929 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
8930 // their first argument) rather than tweaking bar.private_impl.qux fields.
8931 //
8932 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
8933 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
8934 // order to provide convenience methods. These forward on "this", so that you
8935 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
8936 wuffs_json__decoder__struct() = delete;
8937 wuffs_json__decoder__struct(const wuffs_json__decoder__struct&) = delete;
8938 wuffs_json__decoder__struct& operator=(
8939 const wuffs_json__decoder__struct&) = delete;
8940#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
8941
8942#if !defined(WUFFS_IMPLEMENTATION)
8943 // As above, the size of the struct is not part of the public API, and unless
8944 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
8945 // allocated, not stack allocated. Its size is not intended to be known at
8946 // compile time, but it is unfortunately divulged as a side effect of
8947 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
8948 // instead of "sizeof T", invoking the operator. To make the two values
8949 // different, so that passing the latter will be rejected by the initialize
8950 // function, we add an arbitrary amount of dead weight.
8951 uint8_t dead_weight[123000000]; // 123 MB.
8952#endif // !defined(WUFFS_IMPLEMENTATION)
8953
8954 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
8955 initialize(
8956 size_t sizeof_star_self,
8957 uint64_t wuffs_version,
8958 uint32_t options) {
8959 return wuffs_json__decoder__initialize(
8960 this, sizeof_star_self, wuffs_version, options);
8961 }
8962
8963 inline wuffs_base__token_decoder*
8964 upcast_as__wuffs_base__token_decoder() {
8965 return (wuffs_base__token_decoder*)this;
8966 }
8967
8968 inline wuffs_base__empty_struct
8969 set_quirk_enabled(
8970 uint32_t a_quirk,
8971 bool a_enabled) {
8972 return wuffs_json__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
8973 }
8974
8975 inline wuffs_base__range_ii_u64
8976 workbuf_len() const {
8977 return wuffs_json__decoder__workbuf_len(this);
8978 }
8979
8980 inline wuffs_base__status
8981 decode_tokens(
8982 wuffs_base__token_buffer* a_dst,
8983 wuffs_base__io_buffer* a_src,
8984 wuffs_base__slice_u8 a_workbuf) {
8985 return wuffs_json__decoder__decode_tokens(this, a_dst, a_src, a_workbuf);
8986 }
8987
8988#endif // __cplusplus
8989}; // struct wuffs_json__decoder__struct
8990
8991#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
8992
Nigel Taofe9d08f2022-10-28 17:30:51 +11008993#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON) || defined(WUFFS_NONMONOLITHIC)
8994
8995#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC)
8996
Nigel Taoe360a532021-04-05 22:47:03 +10008997// ---------------- Status Codes
8998
8999extern const char wuffs_nie__error__bad_header[];
9000extern const char wuffs_nie__error__unsupported_nie_file[];
9001
9002// ---------------- Public Consts
9003
9004#define WUFFS_NIE__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
9005
9006// ---------------- Struct Declarations
9007
9008typedef struct wuffs_nie__decoder__struct wuffs_nie__decoder;
9009
9010#ifdef __cplusplus
9011extern "C" {
9012#endif
9013
9014// ---------------- Public Initializer Prototypes
9015
9016// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
9017// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
9018//
9019// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
9020// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
9021
9022wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9023wuffs_nie__decoder__initialize(
9024 wuffs_nie__decoder* self,
9025 size_t sizeof_star_self,
9026 uint64_t wuffs_version,
9027 uint32_t options);
9028
9029size_t
9030sizeof__wuffs_nie__decoder();
9031
9032// ---------------- Allocs
9033
9034// These functions allocate and initialize Wuffs structs. They return NULL if
9035// memory allocation fails. If they return non-NULL, there is no need to call
9036// wuffs_foo__bar__initialize, but the caller is responsible for eventually
9037// calling free on the returned pointer. That pointer is effectively a C++
9038// std::unique_ptr<T, decltype(&free)>.
9039
9040wuffs_nie__decoder*
9041wuffs_nie__decoder__alloc();
9042
9043static inline wuffs_base__image_decoder*
9044wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder() {
9045 return (wuffs_base__image_decoder*)(wuffs_nie__decoder__alloc());
9046}
9047
9048// ---------------- Upcasts
9049
9050static inline wuffs_base__image_decoder*
9051wuffs_nie__decoder__upcast_as__wuffs_base__image_decoder(
9052 wuffs_nie__decoder* p) {
9053 return (wuffs_base__image_decoder*)p;
9054}
9055
9056// ---------------- Public Function Prototypes
9057
9058WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9059wuffs_nie__decoder__set_quirk_enabled(
9060 wuffs_nie__decoder* self,
9061 uint32_t a_quirk,
9062 bool a_enabled);
9063
9064WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9065wuffs_nie__decoder__decode_image_config(
9066 wuffs_nie__decoder* self,
9067 wuffs_base__image_config* a_dst,
9068 wuffs_base__io_buffer* a_src);
9069
9070WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9071wuffs_nie__decoder__decode_frame_config(
9072 wuffs_nie__decoder* self,
9073 wuffs_base__frame_config* a_dst,
9074 wuffs_base__io_buffer* a_src);
9075
9076WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9077wuffs_nie__decoder__decode_frame(
9078 wuffs_nie__decoder* self,
9079 wuffs_base__pixel_buffer* a_dst,
9080 wuffs_base__io_buffer* a_src,
9081 wuffs_base__pixel_blend a_blend,
9082 wuffs_base__slice_u8 a_workbuf,
9083 wuffs_base__decode_frame_options* a_opts);
9084
9085WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
9086wuffs_nie__decoder__frame_dirty_rect(
9087 const wuffs_nie__decoder* self);
9088
9089WUFFS_BASE__MAYBE_STATIC uint32_t
9090wuffs_nie__decoder__num_animation_loops(
9091 const wuffs_nie__decoder* self);
9092
9093WUFFS_BASE__MAYBE_STATIC uint64_t
9094wuffs_nie__decoder__num_decoded_frame_configs(
9095 const wuffs_nie__decoder* self);
9096
9097WUFFS_BASE__MAYBE_STATIC uint64_t
9098wuffs_nie__decoder__num_decoded_frames(
9099 const wuffs_nie__decoder* self);
9100
9101WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9102wuffs_nie__decoder__restart_frame(
9103 wuffs_nie__decoder* self,
9104 uint64_t a_index,
9105 uint64_t a_io_position);
9106
9107WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9108wuffs_nie__decoder__set_report_metadata(
9109 wuffs_nie__decoder* self,
9110 uint32_t a_fourcc,
9111 bool a_report);
9112
9113WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9114wuffs_nie__decoder__tell_me_more(
9115 wuffs_nie__decoder* self,
9116 wuffs_base__io_buffer* a_dst,
9117 wuffs_base__more_information* a_minfo,
9118 wuffs_base__io_buffer* a_src);
9119
9120WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9121wuffs_nie__decoder__workbuf_len(
9122 const wuffs_nie__decoder* self);
9123
9124#ifdef __cplusplus
9125} // extern "C"
9126#endif
9127
9128// ---------------- Struct Definitions
9129
9130// These structs' fields, and the sizeof them, are private implementation
9131// details that aren't guaranteed to be stable across Wuffs versions.
9132//
9133// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9134
9135#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9136
9137struct wuffs_nie__decoder__struct {
9138 // Do not access the private_impl's or private_data's fields directly. There
9139 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9140 // the wuffs_foo__bar__baz functions.
9141 //
9142 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9143 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9144
9145 struct {
9146 uint32_t magic;
9147 uint32_t active_coroutine;
9148 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
9149 wuffs_base__vtable null_vtable;
9150
9151 uint32_t f_pixfmt;
9152 uint32_t f_width;
9153 uint32_t f_height;
9154 uint8_t f_call_sequence;
9155 uint32_t f_dst_x;
9156 uint32_t f_dst_y;
9157 wuffs_base__pixel_swizzler f_swizzler;
9158
9159 uint32_t p_decode_image_config[1];
9160 uint32_t p_decode_frame_config[1];
9161 uint32_t p_decode_frame[1];
9162 } private_impl;
9163
9164 struct {
9165 struct {
9166 uint64_t scratch;
9167 } s_decode_image_config[1];
9168 } private_data;
9169
9170#ifdef __cplusplus
9171#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9172 using unique_ptr = std::unique_ptr<wuffs_nie__decoder, decltype(&free)>;
9173
9174 // On failure, the alloc_etc functions return nullptr. They don't throw.
9175
9176 static inline unique_ptr
9177 alloc() {
9178 return unique_ptr(wuffs_nie__decoder__alloc(), &free);
9179 }
9180
9181 static inline wuffs_base__image_decoder::unique_ptr
9182 alloc_as__wuffs_base__image_decoder() {
9183 return wuffs_base__image_decoder::unique_ptr(
9184 wuffs_nie__decoder__alloc_as__wuffs_base__image_decoder(), &free);
9185 }
9186#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9187
9188#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9189 // Disallow constructing or copying an object via standard C++ mechanisms,
9190 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9191 // size and field layout is not part of the public, stable, memory-safe API.
9192 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9193 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9194 // their first argument) rather than tweaking bar.private_impl.qux fields.
9195 //
9196 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9197 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9198 // order to provide convenience methods. These forward on "this", so that you
9199 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9200 wuffs_nie__decoder__struct() = delete;
9201 wuffs_nie__decoder__struct(const wuffs_nie__decoder__struct&) = delete;
9202 wuffs_nie__decoder__struct& operator=(
9203 const wuffs_nie__decoder__struct&) = delete;
9204#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9205
9206#if !defined(WUFFS_IMPLEMENTATION)
9207 // As above, the size of the struct is not part of the public API, and unless
9208 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9209 // allocated, not stack allocated. Its size is not intended to be known at
9210 // compile time, but it is unfortunately divulged as a side effect of
9211 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9212 // instead of "sizeof T", invoking the operator. To make the two values
9213 // different, so that passing the latter will be rejected by the initialize
9214 // function, we add an arbitrary amount of dead weight.
9215 uint8_t dead_weight[123000000]; // 123 MB.
9216#endif // !defined(WUFFS_IMPLEMENTATION)
9217
9218 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9219 initialize(
9220 size_t sizeof_star_self,
9221 uint64_t wuffs_version,
9222 uint32_t options) {
9223 return wuffs_nie__decoder__initialize(
9224 this, sizeof_star_self, wuffs_version, options);
9225 }
9226
9227 inline wuffs_base__image_decoder*
9228 upcast_as__wuffs_base__image_decoder() {
9229 return (wuffs_base__image_decoder*)this;
9230 }
9231
9232 inline wuffs_base__empty_struct
9233 set_quirk_enabled(
9234 uint32_t a_quirk,
9235 bool a_enabled) {
9236 return wuffs_nie__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9237 }
9238
9239 inline wuffs_base__status
9240 decode_image_config(
9241 wuffs_base__image_config* a_dst,
9242 wuffs_base__io_buffer* a_src) {
9243 return wuffs_nie__decoder__decode_image_config(this, a_dst, a_src);
9244 }
9245
9246 inline wuffs_base__status
9247 decode_frame_config(
9248 wuffs_base__frame_config* a_dst,
9249 wuffs_base__io_buffer* a_src) {
9250 return wuffs_nie__decoder__decode_frame_config(this, a_dst, a_src);
9251 }
9252
9253 inline wuffs_base__status
9254 decode_frame(
9255 wuffs_base__pixel_buffer* a_dst,
9256 wuffs_base__io_buffer* a_src,
9257 wuffs_base__pixel_blend a_blend,
9258 wuffs_base__slice_u8 a_workbuf,
9259 wuffs_base__decode_frame_options* a_opts) {
9260 return wuffs_nie__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
9261 }
9262
9263 inline wuffs_base__rect_ie_u32
9264 frame_dirty_rect() const {
9265 return wuffs_nie__decoder__frame_dirty_rect(this);
9266 }
9267
9268 inline uint32_t
9269 num_animation_loops() const {
9270 return wuffs_nie__decoder__num_animation_loops(this);
9271 }
9272
9273 inline uint64_t
9274 num_decoded_frame_configs() const {
9275 return wuffs_nie__decoder__num_decoded_frame_configs(this);
9276 }
9277
9278 inline uint64_t
9279 num_decoded_frames() const {
9280 return wuffs_nie__decoder__num_decoded_frames(this);
9281 }
9282
9283 inline wuffs_base__status
9284 restart_frame(
9285 uint64_t a_index,
9286 uint64_t a_io_position) {
9287 return wuffs_nie__decoder__restart_frame(this, a_index, a_io_position);
9288 }
9289
9290 inline wuffs_base__empty_struct
9291 set_report_metadata(
9292 uint32_t a_fourcc,
9293 bool a_report) {
9294 return wuffs_nie__decoder__set_report_metadata(this, a_fourcc, a_report);
9295 }
9296
9297 inline wuffs_base__status
9298 tell_me_more(
9299 wuffs_base__io_buffer* a_dst,
9300 wuffs_base__more_information* a_minfo,
9301 wuffs_base__io_buffer* a_src) {
9302 return wuffs_nie__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
9303 }
9304
9305 inline wuffs_base__range_ii_u64
9306 workbuf_len() const {
9307 return wuffs_nie__decoder__workbuf_len(this);
9308 }
9309
9310#endif // __cplusplus
9311}; // struct wuffs_nie__decoder__struct
9312
9313#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9314
Nigel Taofe9d08f2022-10-28 17:30:51 +11009315#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE) || defined(WUFFS_NONMONOLITHIC)
9316
9317#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) || defined(WUFFS_NONMONOLITHIC)
9318
Nigel Taoe360a532021-04-05 22:47:03 +10009319// ---------------- Status Codes
9320
9321extern const char wuffs_zlib__note__dictionary_required[];
9322extern const char wuffs_zlib__error__bad_checksum[];
9323extern const char wuffs_zlib__error__bad_compression_method[];
9324extern const char wuffs_zlib__error__bad_compression_window_size[];
9325extern const char wuffs_zlib__error__bad_parity_check[];
9326extern const char wuffs_zlib__error__incorrect_dictionary[];
9327
9328// ---------------- Public Consts
9329
Nigel Taoebbecaa2022-01-08 14:08:27 +11009330#define WUFFS_ZLIB__QUIRK_JUST_RAW_DEFLATE 2113790976
9331
Nigel Taoe360a532021-04-05 22:47:03 +10009332#define WUFFS_ZLIB__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 1
9333
9334// ---------------- Struct Declarations
9335
9336typedef struct wuffs_zlib__decoder__struct wuffs_zlib__decoder;
9337
9338#ifdef __cplusplus
9339extern "C" {
9340#endif
9341
9342// ---------------- Public Initializer Prototypes
9343
9344// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
9345// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
9346//
9347// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
9348// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
9349
9350wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9351wuffs_zlib__decoder__initialize(
9352 wuffs_zlib__decoder* self,
9353 size_t sizeof_star_self,
9354 uint64_t wuffs_version,
9355 uint32_t options);
9356
9357size_t
9358sizeof__wuffs_zlib__decoder();
9359
9360// ---------------- Allocs
9361
9362// These functions allocate and initialize Wuffs structs. They return NULL if
9363// memory allocation fails. If they return non-NULL, there is no need to call
9364// wuffs_foo__bar__initialize, but the caller is responsible for eventually
9365// calling free on the returned pointer. That pointer is effectively a C++
9366// std::unique_ptr<T, decltype(&free)>.
9367
9368wuffs_zlib__decoder*
9369wuffs_zlib__decoder__alloc();
9370
9371static inline wuffs_base__io_transformer*
9372wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer() {
9373 return (wuffs_base__io_transformer*)(wuffs_zlib__decoder__alloc());
9374}
9375
9376// ---------------- Upcasts
9377
9378static inline wuffs_base__io_transformer*
9379wuffs_zlib__decoder__upcast_as__wuffs_base__io_transformer(
9380 wuffs_zlib__decoder* p) {
9381 return (wuffs_base__io_transformer*)p;
9382}
9383
9384// ---------------- Public Function Prototypes
9385
9386WUFFS_BASE__MAYBE_STATIC uint32_t
9387wuffs_zlib__decoder__dictionary_id(
9388 const wuffs_zlib__decoder* self);
9389
9390WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9391wuffs_zlib__decoder__add_dictionary(
9392 wuffs_zlib__decoder* self,
9393 wuffs_base__slice_u8 a_dict);
9394
9395WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9396wuffs_zlib__decoder__set_quirk_enabled(
9397 wuffs_zlib__decoder* self,
9398 uint32_t a_quirk,
9399 bool a_enabled);
9400
9401WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9402wuffs_zlib__decoder__workbuf_len(
9403 const wuffs_zlib__decoder* self);
9404
9405WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9406wuffs_zlib__decoder__transform_io(
9407 wuffs_zlib__decoder* self,
9408 wuffs_base__io_buffer* a_dst,
9409 wuffs_base__io_buffer* a_src,
9410 wuffs_base__slice_u8 a_workbuf);
9411
9412#ifdef __cplusplus
9413} // extern "C"
9414#endif
9415
9416// ---------------- Struct Definitions
9417
9418// These structs' fields, and the sizeof them, are private implementation
9419// details that aren't guaranteed to be stable across Wuffs versions.
9420//
9421// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9422
9423#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9424
9425struct wuffs_zlib__decoder__struct {
9426 // Do not access the private_impl's or private_data's fields directly. There
9427 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9428 // the wuffs_foo__bar__baz functions.
9429 //
9430 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9431 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9432
9433 struct {
9434 uint32_t magic;
9435 uint32_t active_coroutine;
9436 wuffs_base__vtable vtable_for__wuffs_base__io_transformer;
9437 wuffs_base__vtable null_vtable;
9438
9439 bool f_bad_call_sequence;
9440 bool f_header_complete;
9441 bool f_got_dictionary;
9442 bool f_want_dictionary;
Nigel Taoebbecaa2022-01-08 14:08:27 +11009443 bool f_quirks[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009444 bool f_ignore_checksum;
9445 uint32_t f_dict_id_got;
9446 uint32_t f_dict_id_want;
9447
9448 uint32_t p_transform_io[1];
9449 } private_impl;
9450
9451 struct {
9452 wuffs_adler32__hasher f_checksum;
9453 wuffs_adler32__hasher f_dict_id_hasher;
9454 wuffs_deflate__decoder f_flate;
9455
9456 struct {
9457 uint32_t v_checksum_got;
9458 uint64_t scratch;
9459 } s_transform_io[1];
9460 } private_data;
9461
9462#ifdef __cplusplus
9463#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9464 using unique_ptr = std::unique_ptr<wuffs_zlib__decoder, decltype(&free)>;
9465
9466 // On failure, the alloc_etc functions return nullptr. They don't throw.
9467
9468 static inline unique_ptr
9469 alloc() {
9470 return unique_ptr(wuffs_zlib__decoder__alloc(), &free);
9471 }
9472
9473 static inline wuffs_base__io_transformer::unique_ptr
9474 alloc_as__wuffs_base__io_transformer() {
9475 return wuffs_base__io_transformer::unique_ptr(
9476 wuffs_zlib__decoder__alloc_as__wuffs_base__io_transformer(), &free);
9477 }
9478#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9479
9480#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9481 // Disallow constructing or copying an object via standard C++ mechanisms,
9482 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9483 // size and field layout is not part of the public, stable, memory-safe API.
9484 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9485 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9486 // their first argument) rather than tweaking bar.private_impl.qux fields.
9487 //
9488 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9489 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9490 // order to provide convenience methods. These forward on "this", so that you
9491 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9492 wuffs_zlib__decoder__struct() = delete;
9493 wuffs_zlib__decoder__struct(const wuffs_zlib__decoder__struct&) = delete;
9494 wuffs_zlib__decoder__struct& operator=(
9495 const wuffs_zlib__decoder__struct&) = delete;
9496#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9497
9498#if !defined(WUFFS_IMPLEMENTATION)
9499 // As above, the size of the struct is not part of the public API, and unless
9500 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9501 // allocated, not stack allocated. Its size is not intended to be known at
9502 // compile time, but it is unfortunately divulged as a side effect of
9503 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9504 // instead of "sizeof T", invoking the operator. To make the two values
9505 // different, so that passing the latter will be rejected by the initialize
9506 // function, we add an arbitrary amount of dead weight.
9507 uint8_t dead_weight[123000000]; // 123 MB.
9508#endif // !defined(WUFFS_IMPLEMENTATION)
9509
9510 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9511 initialize(
9512 size_t sizeof_star_self,
9513 uint64_t wuffs_version,
9514 uint32_t options) {
9515 return wuffs_zlib__decoder__initialize(
9516 this, sizeof_star_self, wuffs_version, options);
9517 }
9518
9519 inline wuffs_base__io_transformer*
9520 upcast_as__wuffs_base__io_transformer() {
9521 return (wuffs_base__io_transformer*)this;
9522 }
9523
9524 inline uint32_t
9525 dictionary_id() const {
9526 return wuffs_zlib__decoder__dictionary_id(this);
9527 }
9528
9529 inline wuffs_base__empty_struct
9530 add_dictionary(
9531 wuffs_base__slice_u8 a_dict) {
9532 return wuffs_zlib__decoder__add_dictionary(this, a_dict);
9533 }
9534
9535 inline wuffs_base__empty_struct
9536 set_quirk_enabled(
9537 uint32_t a_quirk,
9538 bool a_enabled) {
9539 return wuffs_zlib__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9540 }
9541
9542 inline wuffs_base__range_ii_u64
9543 workbuf_len() const {
9544 return wuffs_zlib__decoder__workbuf_len(this);
9545 }
9546
9547 inline wuffs_base__status
9548 transform_io(
9549 wuffs_base__io_buffer* a_dst,
9550 wuffs_base__io_buffer* a_src,
9551 wuffs_base__slice_u8 a_workbuf) {
9552 return wuffs_zlib__decoder__transform_io(this, a_dst, a_src, a_workbuf);
9553 }
9554
9555#endif // __cplusplus
9556}; // struct wuffs_zlib__decoder__struct
9557
9558#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9559
Nigel Taofe9d08f2022-10-28 17:30:51 +11009560#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB) || defined(WUFFS_NONMONOLITHIC)
9561
9562#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) || defined(WUFFS_NONMONOLITHIC)
9563
Nigel Taoe360a532021-04-05 22:47:03 +10009564// ---------------- Status Codes
9565
Nigel Taobf9dab32021-11-18 19:19:55 +11009566extern const char wuffs_png__error__bad_animation_sequence_number[];
Nigel Taoe360a532021-04-05 22:47:03 +10009567extern const char wuffs_png__error__bad_checksum[];
9568extern const char wuffs_png__error__bad_chunk[];
9569extern const char wuffs_png__error__bad_filter[];
9570extern const char wuffs_png__error__bad_header[];
Nigel Taobf9dab32021-11-18 19:19:55 +11009571extern const char wuffs_png__error__bad_text_chunk_not_latin_1[];
Nigel Taoe360a532021-04-05 22:47:03 +10009572extern const char wuffs_png__error__missing_palette[];
Nigel Tao123a5c62022-06-03 14:17:20 +10009573extern const char wuffs_png__error__unsupported_cgbi_extension[];
Nigel Taobf9dab32021-11-18 19:19:55 +11009574extern const char wuffs_png__error__unsupported_png_compression_method[];
Nigel Taoe360a532021-04-05 22:47:03 +10009575extern const char wuffs_png__error__unsupported_png_file[];
9576
9577// ---------------- Public Consts
9578
Nigel Tao123a5c62022-06-03 14:17:20 +10009579#define WUFFS_PNG__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 2251799562027015
Nigel Taoe360a532021-04-05 22:47:03 +10009580
Nigel Taobf9dab32021-11-18 19:19:55 +11009581#define WUFFS_PNG__DECODER_SRC_IO_BUFFER_LENGTH_MIN_INCL 8
9582
Nigel Taoe360a532021-04-05 22:47:03 +10009583// ---------------- Struct Declarations
9584
9585typedef struct wuffs_png__decoder__struct wuffs_png__decoder;
9586
9587#ifdef __cplusplus
9588extern "C" {
9589#endif
9590
9591// ---------------- Public Initializer Prototypes
9592
9593// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
9594// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
9595//
9596// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
9597// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
9598
9599wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9600wuffs_png__decoder__initialize(
9601 wuffs_png__decoder* self,
9602 size_t sizeof_star_self,
9603 uint64_t wuffs_version,
9604 uint32_t options);
9605
9606size_t
9607sizeof__wuffs_png__decoder();
9608
9609// ---------------- Allocs
9610
9611// These functions allocate and initialize Wuffs structs. They return NULL if
9612// memory allocation fails. If they return non-NULL, there is no need to call
9613// wuffs_foo__bar__initialize, but the caller is responsible for eventually
9614// calling free on the returned pointer. That pointer is effectively a C++
9615// std::unique_ptr<T, decltype(&free)>.
9616
9617wuffs_png__decoder*
9618wuffs_png__decoder__alloc();
9619
9620static inline wuffs_base__image_decoder*
9621wuffs_png__decoder__alloc_as__wuffs_base__image_decoder() {
9622 return (wuffs_base__image_decoder*)(wuffs_png__decoder__alloc());
9623}
9624
9625// ---------------- Upcasts
9626
9627static inline wuffs_base__image_decoder*
9628wuffs_png__decoder__upcast_as__wuffs_base__image_decoder(
9629 wuffs_png__decoder* p) {
9630 return (wuffs_base__image_decoder*)p;
9631}
9632
9633// ---------------- Public Function Prototypes
9634
9635WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9636wuffs_png__decoder__set_quirk_enabled(
9637 wuffs_png__decoder* self,
9638 uint32_t a_quirk,
9639 bool a_enabled);
9640
9641WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9642wuffs_png__decoder__decode_image_config(
9643 wuffs_png__decoder* self,
9644 wuffs_base__image_config* a_dst,
9645 wuffs_base__io_buffer* a_src);
9646
9647WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9648wuffs_png__decoder__decode_frame_config(
9649 wuffs_png__decoder* self,
9650 wuffs_base__frame_config* a_dst,
9651 wuffs_base__io_buffer* a_src);
9652
9653WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9654wuffs_png__decoder__decode_frame(
9655 wuffs_png__decoder* self,
9656 wuffs_base__pixel_buffer* a_dst,
9657 wuffs_base__io_buffer* a_src,
9658 wuffs_base__pixel_blend a_blend,
9659 wuffs_base__slice_u8 a_workbuf,
9660 wuffs_base__decode_frame_options* a_opts);
9661
9662WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
9663wuffs_png__decoder__frame_dirty_rect(
9664 const wuffs_png__decoder* self);
9665
9666WUFFS_BASE__MAYBE_STATIC uint32_t
9667wuffs_png__decoder__num_animation_loops(
9668 const wuffs_png__decoder* self);
9669
9670WUFFS_BASE__MAYBE_STATIC uint64_t
9671wuffs_png__decoder__num_decoded_frame_configs(
9672 const wuffs_png__decoder* self);
9673
9674WUFFS_BASE__MAYBE_STATIC uint64_t
9675wuffs_png__decoder__num_decoded_frames(
9676 const wuffs_png__decoder* self);
9677
9678WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9679wuffs_png__decoder__restart_frame(
9680 wuffs_png__decoder* self,
9681 uint64_t a_index,
9682 uint64_t a_io_position);
9683
9684WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
9685wuffs_png__decoder__set_report_metadata(
9686 wuffs_png__decoder* self,
9687 uint32_t a_fourcc,
9688 bool a_report);
9689
9690WUFFS_BASE__MAYBE_STATIC wuffs_base__status
9691wuffs_png__decoder__tell_me_more(
9692 wuffs_png__decoder* self,
9693 wuffs_base__io_buffer* a_dst,
9694 wuffs_base__more_information* a_minfo,
9695 wuffs_base__io_buffer* a_src);
9696
9697WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
9698wuffs_png__decoder__workbuf_len(
9699 const wuffs_png__decoder* self);
9700
9701#ifdef __cplusplus
9702} // extern "C"
9703#endif
9704
9705// ---------------- Struct Definitions
9706
9707// These structs' fields, and the sizeof them, are private implementation
9708// details that aren't guaranteed to be stable across Wuffs versions.
9709//
9710// See https://en.wikipedia.org/wiki/Opaque_pointer#C
9711
9712#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
9713
9714struct wuffs_png__decoder__struct {
9715 // Do not access the private_impl's or private_data's fields directly. There
9716 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
9717 // the wuffs_foo__bar__baz functions.
9718 //
9719 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
9720 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
9721
9722 struct {
9723 uint32_t magic;
9724 uint32_t active_coroutine;
9725 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
9726 wuffs_base__vtable null_vtable;
9727
9728 uint32_t f_width;
9729 uint32_t f_height;
9730 uint64_t f_pass_bytes_per_row;
9731 uint64_t f_workbuf_wi;
Nigel Tao7804ffe2021-10-07 21:58:26 +11009732 uint64_t f_workbuf_hist_pos_base;
Nigel Taoe360a532021-04-05 22:47:03 +10009733 uint64_t f_overall_workbuf_length;
9734 uint64_t f_pass_workbuf_length;
9735 uint8_t f_call_sequence;
Nigel Taobf9dab32021-11-18 19:19:55 +11009736 bool f_report_metadata_chrm;
Nigel Taoebbecaa2022-01-08 14:08:27 +11009737 bool f_report_metadata_exif;
Nigel Taobf9dab32021-11-18 19:19:55 +11009738 bool f_report_metadata_gama;
9739 bool f_report_metadata_iccp;
9740 bool f_report_metadata_kvp;
9741 bool f_report_metadata_srgb;
Nigel Taoe360a532021-04-05 22:47:03 +10009742 bool f_ignore_checksum;
9743 uint8_t f_depth;
9744 uint8_t f_color_type;
9745 uint8_t f_filter_distance;
9746 uint8_t f_interlace_pass;
Nigel Taobf9dab32021-11-18 19:19:55 +11009747 bool f_seen_actl;
9748 bool f_seen_chrm;
9749 bool f_seen_fctl;
Nigel Taoebbecaa2022-01-08 14:08:27 +11009750 bool f_seen_exif;
Nigel Taobf9dab32021-11-18 19:19:55 +11009751 bool f_seen_gama;
9752 bool f_seen_iccp;
9753 bool f_seen_idat;
Nigel Tao123a5c62022-06-03 14:17:20 +10009754 bool f_seen_ihdr;
Nigel Taoe360a532021-04-05 22:47:03 +10009755 bool f_seen_plte;
Nigel Taobf9dab32021-11-18 19:19:55 +11009756 bool f_seen_srgb;
Nigel Taoe360a532021-04-05 22:47:03 +10009757 bool f_seen_trns;
Nigel Taobf9dab32021-11-18 19:19:55 +11009758 bool f_metadata_is_zlib_compressed;
9759 bool f_zlib_is_dirty;
Nigel Taoe360a532021-04-05 22:47:03 +10009760 uint32_t f_chunk_type;
9761 uint8_t f_chunk_type_array[4];
Nigel Taobf9dab32021-11-18 19:19:55 +11009762 uint32_t f_chunk_length;
9763 uint64_t f_remap_transparency;
9764 uint32_t f_dst_pixfmt;
9765 uint32_t f_src_pixfmt;
9766 uint32_t f_num_animation_frames_value;
9767 uint32_t f_num_animation_loops_value;
9768 uint32_t f_num_decoded_frame_configs_value;
9769 uint32_t f_num_decoded_frames_value;
9770 uint32_t f_frame_rect_x0;
9771 uint32_t f_frame_rect_y0;
9772 uint32_t f_frame_rect_x1;
9773 uint32_t f_frame_rect_y1;
9774 uint32_t f_first_rect_x0;
9775 uint32_t f_first_rect_y0;
9776 uint32_t f_first_rect_x1;
9777 uint32_t f_first_rect_y1;
Nigel Taoe360a532021-04-05 22:47:03 +10009778 uint64_t f_frame_config_io_position;
Nigel Taobf9dab32021-11-18 19:19:55 +11009779 uint64_t f_first_config_io_position;
9780 uint64_t f_frame_duration;
9781 uint64_t f_first_duration;
9782 uint8_t f_frame_disposal;
9783 uint8_t f_first_disposal;
9784 bool f_frame_overwrite_instead_of_blend;
9785 bool f_first_overwrite_instead_of_blend;
9786 uint32_t f_next_animation_seq_num;
9787 uint32_t f_metadata_flavor;
9788 uint32_t f_metadata_fourcc;
9789 uint64_t f_metadata_x;
9790 uint64_t f_metadata_y;
9791 uint64_t f_metadata_z;
9792 uint32_t f_ztxt_ri;
9793 uint32_t f_ztxt_wi;
9794 uint64_t f_ztxt_hist_pos;
Nigel Taoe360a532021-04-05 22:47:03 +10009795 wuffs_base__pixel_swizzler f_swizzler;
9796
9797 wuffs_base__empty_struct (*choosy_filter_1)(
9798 wuffs_png__decoder* self,
9799 wuffs_base__slice_u8 a_curr);
9800 wuffs_base__empty_struct (*choosy_filter_3)(
9801 wuffs_png__decoder* self,
9802 wuffs_base__slice_u8 a_curr,
9803 wuffs_base__slice_u8 a_prev);
9804 wuffs_base__empty_struct (*choosy_filter_4)(
9805 wuffs_png__decoder* self,
9806 wuffs_base__slice_u8 a_curr,
9807 wuffs_base__slice_u8 a_prev);
9808 uint32_t p_decode_image_config[1];
9809 uint32_t p_decode_ihdr[1];
9810 uint32_t p_decode_other_chunk[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009811 uint32_t p_decode_actl[1];
9812 uint32_t p_decode_chrm[1];
9813 uint32_t p_decode_fctl[1];
9814 uint32_t p_decode_gama[1];
9815 uint32_t p_decode_iccp[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009816 uint32_t p_decode_plte[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009817 uint32_t p_decode_srgb[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009818 uint32_t p_decode_trns[1];
9819 uint32_t p_decode_frame_config[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009820 uint32_t p_skip_frame[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009821 uint32_t p_decode_frame[1];
9822 uint32_t p_decode_pass[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009823 uint32_t p_tell_me_more[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009824 wuffs_base__status (*choosy_filter_and_swizzle)(
9825 wuffs_png__decoder* self,
9826 wuffs_base__pixel_buffer* a_dst,
9827 wuffs_base__slice_u8 a_workbuf);
9828 } private_impl;
9829
9830 struct {
9831 wuffs_crc32__ieee_hasher f_crc32;
9832 wuffs_zlib__decoder f_zlib;
9833 uint8_t f_dst_palette[1024];
9834 uint8_t f_src_palette[1024];
9835
9836 struct {
9837 uint32_t v_checksum_have;
9838 uint64_t scratch;
9839 } s_decode_image_config[1];
9840 struct {
9841 uint64_t scratch;
9842 } s_decode_ihdr[1];
9843 struct {
9844 uint64_t scratch;
9845 } s_decode_other_chunk[1];
9846 struct {
Nigel Taobf9dab32021-11-18 19:19:55 +11009847 uint64_t scratch;
9848 } s_decode_actl[1];
9849 struct {
9850 uint64_t scratch;
9851 } s_decode_chrm[1];
9852 struct {
9853 uint32_t v_x0;
9854 uint32_t v_x1;
9855 uint32_t v_y1;
9856 uint64_t scratch;
9857 } s_decode_fctl[1];
9858 struct {
9859 uint64_t scratch;
9860 } s_decode_gama[1];
9861 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009862 uint32_t v_num_entries;
9863 uint32_t v_i;
9864 uint64_t scratch;
9865 } s_decode_plte[1];
9866 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009867 uint32_t v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +11009868 uint32_t v_n;
9869 uint64_t scratch;
Nigel Taoe360a532021-04-05 22:47:03 +10009870 } s_decode_trns[1];
9871 struct {
Nigel Taobf9dab32021-11-18 19:19:55 +11009872 uint64_t scratch;
9873 } s_decode_frame_config[1];
9874 struct {
9875 uint64_t scratch;
9876 } s_skip_frame[1];
9877 struct {
9878 uint64_t scratch;
9879 } s_decode_frame[1];
9880 struct {
Nigel Taoe360a532021-04-05 22:47:03 +10009881 uint64_t scratch;
9882 } s_decode_pass[1];
Nigel Taobf9dab32021-11-18 19:19:55 +11009883 struct {
9884 wuffs_base__status v_zlib_status;
9885 uint64_t scratch;
9886 } s_tell_me_more[1];
Nigel Taoe360a532021-04-05 22:47:03 +10009887 } private_data;
9888
9889#ifdef __cplusplus
9890#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9891 using unique_ptr = std::unique_ptr<wuffs_png__decoder, decltype(&free)>;
9892
9893 // On failure, the alloc_etc functions return nullptr. They don't throw.
9894
9895 static inline unique_ptr
9896 alloc() {
9897 return unique_ptr(wuffs_png__decoder__alloc(), &free);
9898 }
9899
9900 static inline wuffs_base__image_decoder::unique_ptr
9901 alloc_as__wuffs_base__image_decoder() {
9902 return wuffs_base__image_decoder::unique_ptr(
9903 wuffs_png__decoder__alloc_as__wuffs_base__image_decoder(), &free);
9904 }
9905#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
9906
9907#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9908 // Disallow constructing or copying an object via standard C++ mechanisms,
9909 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
9910 // size and field layout is not part of the public, stable, memory-safe API.
9911 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
9912 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
9913 // their first argument) rather than tweaking bar.private_impl.qux fields.
9914 //
9915 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
9916 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
9917 // order to provide convenience methods. These forward on "this", so that you
9918 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
9919 wuffs_png__decoder__struct() = delete;
9920 wuffs_png__decoder__struct(const wuffs_png__decoder__struct&) = delete;
9921 wuffs_png__decoder__struct& operator=(
9922 const wuffs_png__decoder__struct&) = delete;
9923#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
9924
9925#if !defined(WUFFS_IMPLEMENTATION)
9926 // As above, the size of the struct is not part of the public API, and unless
9927 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
9928 // allocated, not stack allocated. Its size is not intended to be known at
9929 // compile time, but it is unfortunately divulged as a side effect of
9930 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
9931 // instead of "sizeof T", invoking the operator. To make the two values
9932 // different, so that passing the latter will be rejected by the initialize
9933 // function, we add an arbitrary amount of dead weight.
9934 uint8_t dead_weight[123000000]; // 123 MB.
9935#endif // !defined(WUFFS_IMPLEMENTATION)
9936
9937 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
9938 initialize(
9939 size_t sizeof_star_self,
9940 uint64_t wuffs_version,
9941 uint32_t options) {
9942 return wuffs_png__decoder__initialize(
9943 this, sizeof_star_self, wuffs_version, options);
9944 }
9945
9946 inline wuffs_base__image_decoder*
9947 upcast_as__wuffs_base__image_decoder() {
9948 return (wuffs_base__image_decoder*)this;
9949 }
9950
9951 inline wuffs_base__empty_struct
9952 set_quirk_enabled(
9953 uint32_t a_quirk,
9954 bool a_enabled) {
9955 return wuffs_png__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
9956 }
9957
9958 inline wuffs_base__status
9959 decode_image_config(
9960 wuffs_base__image_config* a_dst,
9961 wuffs_base__io_buffer* a_src) {
9962 return wuffs_png__decoder__decode_image_config(this, a_dst, a_src);
9963 }
9964
9965 inline wuffs_base__status
9966 decode_frame_config(
9967 wuffs_base__frame_config* a_dst,
9968 wuffs_base__io_buffer* a_src) {
9969 return wuffs_png__decoder__decode_frame_config(this, a_dst, a_src);
9970 }
9971
9972 inline wuffs_base__status
9973 decode_frame(
9974 wuffs_base__pixel_buffer* a_dst,
9975 wuffs_base__io_buffer* a_src,
9976 wuffs_base__pixel_blend a_blend,
9977 wuffs_base__slice_u8 a_workbuf,
9978 wuffs_base__decode_frame_options* a_opts) {
9979 return wuffs_png__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
9980 }
9981
9982 inline wuffs_base__rect_ie_u32
9983 frame_dirty_rect() const {
9984 return wuffs_png__decoder__frame_dirty_rect(this);
9985 }
9986
9987 inline uint32_t
9988 num_animation_loops() const {
9989 return wuffs_png__decoder__num_animation_loops(this);
9990 }
9991
9992 inline uint64_t
9993 num_decoded_frame_configs() const {
9994 return wuffs_png__decoder__num_decoded_frame_configs(this);
9995 }
9996
9997 inline uint64_t
9998 num_decoded_frames() const {
9999 return wuffs_png__decoder__num_decoded_frames(this);
10000 }
10001
10002 inline wuffs_base__status
10003 restart_frame(
10004 uint64_t a_index,
10005 uint64_t a_io_position) {
10006 return wuffs_png__decoder__restart_frame(this, a_index, a_io_position);
10007 }
10008
10009 inline wuffs_base__empty_struct
10010 set_report_metadata(
10011 uint32_t a_fourcc,
10012 bool a_report) {
10013 return wuffs_png__decoder__set_report_metadata(this, a_fourcc, a_report);
10014 }
10015
10016 inline wuffs_base__status
10017 tell_me_more(
10018 wuffs_base__io_buffer* a_dst,
10019 wuffs_base__more_information* a_minfo,
10020 wuffs_base__io_buffer* a_src) {
10021 return wuffs_png__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
10022 }
10023
10024 inline wuffs_base__range_ii_u64
10025 workbuf_len() const {
10026 return wuffs_png__decoder__workbuf_len(this);
10027 }
10028
10029#endif // __cplusplus
10030}; // struct wuffs_png__decoder__struct
10031
10032#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
10033
Nigel Taofe9d08f2022-10-28 17:30:51 +110010034#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG) || defined(WUFFS_NONMONOLITHIC)
10035
10036#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC)
10037
Nigel Taoe360a532021-04-05 22:47:03 +100010038// ---------------- Status Codes
10039
Nigel Taocc74cb42022-01-19 11:06:15 +110010040extern const char wuffs_tga__error__bad_header[];
10041extern const char wuffs_tga__error__bad_run_length_encoding[];
10042extern const char wuffs_tga__error__unsupported_tga_file[];
10043
10044// ---------------- Public Consts
10045
10046#define WUFFS_TGA__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
10047
10048// ---------------- Struct Declarations
10049
10050typedef struct wuffs_tga__decoder__struct wuffs_tga__decoder;
10051
10052#ifdef __cplusplus
10053extern "C" {
10054#endif
10055
10056// ---------------- Public Initializer Prototypes
10057
10058// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
10059// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
10060//
10061// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
10062// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
10063
10064wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
10065wuffs_tga__decoder__initialize(
10066 wuffs_tga__decoder* self,
10067 size_t sizeof_star_self,
10068 uint64_t wuffs_version,
10069 uint32_t options);
10070
10071size_t
10072sizeof__wuffs_tga__decoder();
10073
10074// ---------------- Allocs
10075
10076// These functions allocate and initialize Wuffs structs. They return NULL if
10077// memory allocation fails. If they return non-NULL, there is no need to call
10078// wuffs_foo__bar__initialize, but the caller is responsible for eventually
10079// calling free on the returned pointer. That pointer is effectively a C++
10080// std::unique_ptr<T, decltype(&free)>.
10081
10082wuffs_tga__decoder*
10083wuffs_tga__decoder__alloc();
10084
10085static inline wuffs_base__image_decoder*
10086wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder() {
10087 return (wuffs_base__image_decoder*)(wuffs_tga__decoder__alloc());
10088}
10089
10090// ---------------- Upcasts
10091
10092static inline wuffs_base__image_decoder*
10093wuffs_tga__decoder__upcast_as__wuffs_base__image_decoder(
10094 wuffs_tga__decoder* p) {
10095 return (wuffs_base__image_decoder*)p;
10096}
10097
10098// ---------------- Public Function Prototypes
10099
10100WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
10101wuffs_tga__decoder__set_quirk_enabled(
10102 wuffs_tga__decoder* self,
10103 uint32_t a_quirk,
10104 bool a_enabled);
10105
10106WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10107wuffs_tga__decoder__decode_image_config(
10108 wuffs_tga__decoder* self,
10109 wuffs_base__image_config* a_dst,
10110 wuffs_base__io_buffer* a_src);
10111
10112WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10113wuffs_tga__decoder__decode_frame_config(
10114 wuffs_tga__decoder* self,
10115 wuffs_base__frame_config* a_dst,
10116 wuffs_base__io_buffer* a_src);
10117
10118WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10119wuffs_tga__decoder__decode_frame(
10120 wuffs_tga__decoder* self,
10121 wuffs_base__pixel_buffer* a_dst,
10122 wuffs_base__io_buffer* a_src,
10123 wuffs_base__pixel_blend a_blend,
10124 wuffs_base__slice_u8 a_workbuf,
10125 wuffs_base__decode_frame_options* a_opts);
10126
10127WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
10128wuffs_tga__decoder__frame_dirty_rect(
10129 const wuffs_tga__decoder* self);
10130
10131WUFFS_BASE__MAYBE_STATIC uint32_t
10132wuffs_tga__decoder__num_animation_loops(
10133 const wuffs_tga__decoder* self);
10134
10135WUFFS_BASE__MAYBE_STATIC uint64_t
10136wuffs_tga__decoder__num_decoded_frame_configs(
10137 const wuffs_tga__decoder* self);
10138
10139WUFFS_BASE__MAYBE_STATIC uint64_t
10140wuffs_tga__decoder__num_decoded_frames(
10141 const wuffs_tga__decoder* self);
10142
10143WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10144wuffs_tga__decoder__restart_frame(
10145 wuffs_tga__decoder* self,
10146 uint64_t a_index,
10147 uint64_t a_io_position);
10148
10149WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
10150wuffs_tga__decoder__set_report_metadata(
10151 wuffs_tga__decoder* self,
10152 uint32_t a_fourcc,
10153 bool a_report);
10154
10155WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10156wuffs_tga__decoder__tell_me_more(
10157 wuffs_tga__decoder* self,
10158 wuffs_base__io_buffer* a_dst,
10159 wuffs_base__more_information* a_minfo,
10160 wuffs_base__io_buffer* a_src);
10161
10162WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
10163wuffs_tga__decoder__workbuf_len(
10164 const wuffs_tga__decoder* self);
10165
10166#ifdef __cplusplus
10167} // extern "C"
10168#endif
10169
10170// ---------------- Struct Definitions
10171
10172// These structs' fields, and the sizeof them, are private implementation
10173// details that aren't guaranteed to be stable across Wuffs versions.
10174//
10175// See https://en.wikipedia.org/wiki/Opaque_pointer#C
10176
10177#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
10178
10179struct wuffs_tga__decoder__struct {
10180 // Do not access the private_impl's or private_data's fields directly. There
10181 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
10182 // the wuffs_foo__bar__baz functions.
10183 //
10184 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
10185 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
10186
10187 struct {
10188 uint32_t magic;
10189 uint32_t active_coroutine;
10190 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
10191 wuffs_base__vtable null_vtable;
10192
10193 uint32_t f_width;
10194 uint32_t f_height;
10195 uint8_t f_call_sequence;
10196 uint8_t f_header_id_length;
10197 uint8_t f_header_color_map_type;
10198 uint8_t f_header_image_type;
10199 uint16_t f_header_color_map_first_entry_index;
10200 uint16_t f_header_color_map_length;
10201 uint8_t f_header_color_map_entry_size;
10202 uint8_t f_header_pixel_depth;
10203 uint8_t f_header_image_descriptor;
10204 bool f_opaque;
10205 uint32_t f_scratch_bytes_per_pixel;
10206 uint32_t f_src_bytes_per_pixel;
10207 uint32_t f_src_pixfmt;
10208 uint64_t f_frame_config_io_position;
10209 wuffs_base__pixel_swizzler f_swizzler;
10210
10211 uint32_t p_decode_image_config[1];
10212 uint32_t p_decode_frame_config[1];
10213 uint32_t p_decode_frame[1];
10214 } private_impl;
10215
10216 struct {
10217 uint8_t f_dst_palette[1024];
10218 uint8_t f_src_palette[1024];
10219 uint8_t f_scratch[4];
10220
10221 struct {
10222 uint32_t v_i;
10223 uint64_t scratch;
10224 } s_decode_image_config[1];
10225 struct {
10226 uint64_t v_dst_bytes_per_pixel;
10227 uint32_t v_dst_x;
10228 uint32_t v_dst_y;
10229 uint64_t v_mark;
10230 uint32_t v_num_pixels32;
10231 uint32_t v_lit_length;
10232 uint32_t v_run_length;
10233 uint64_t v_num_dst_bytes;
10234 uint64_t scratch;
10235 } s_decode_frame[1];
10236 } private_data;
10237
10238#ifdef __cplusplus
10239#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10240 using unique_ptr = std::unique_ptr<wuffs_tga__decoder, decltype(&free)>;
10241
10242 // On failure, the alloc_etc functions return nullptr. They don't throw.
10243
10244 static inline unique_ptr
10245 alloc() {
10246 return unique_ptr(wuffs_tga__decoder__alloc(), &free);
10247 }
10248
10249 static inline wuffs_base__image_decoder::unique_ptr
10250 alloc_as__wuffs_base__image_decoder() {
10251 return wuffs_base__image_decoder::unique_ptr(
10252 wuffs_tga__decoder__alloc_as__wuffs_base__image_decoder(), &free);
10253 }
10254#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10255
10256#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
10257 // Disallow constructing or copying an object via standard C++ mechanisms,
10258 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
10259 // size and field layout is not part of the public, stable, memory-safe API.
10260 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
10261 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
10262 // their first argument) rather than tweaking bar.private_impl.qux fields.
10263 //
10264 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
10265 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
10266 // order to provide convenience methods. These forward on "this", so that you
10267 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
10268 wuffs_tga__decoder__struct() = delete;
10269 wuffs_tga__decoder__struct(const wuffs_tga__decoder__struct&) = delete;
10270 wuffs_tga__decoder__struct& operator=(
10271 const wuffs_tga__decoder__struct&) = delete;
10272#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
10273
10274#if !defined(WUFFS_IMPLEMENTATION)
10275 // As above, the size of the struct is not part of the public API, and unless
10276 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
10277 // allocated, not stack allocated. Its size is not intended to be known at
10278 // compile time, but it is unfortunately divulged as a side effect of
10279 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
10280 // instead of "sizeof T", invoking the operator. To make the two values
10281 // different, so that passing the latter will be rejected by the initialize
10282 // function, we add an arbitrary amount of dead weight.
10283 uint8_t dead_weight[123000000]; // 123 MB.
10284#endif // !defined(WUFFS_IMPLEMENTATION)
10285
10286 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
10287 initialize(
10288 size_t sizeof_star_self,
10289 uint64_t wuffs_version,
10290 uint32_t options) {
10291 return wuffs_tga__decoder__initialize(
10292 this, sizeof_star_self, wuffs_version, options);
10293 }
10294
10295 inline wuffs_base__image_decoder*
10296 upcast_as__wuffs_base__image_decoder() {
10297 return (wuffs_base__image_decoder*)this;
10298 }
10299
10300 inline wuffs_base__empty_struct
10301 set_quirk_enabled(
10302 uint32_t a_quirk,
10303 bool a_enabled) {
10304 return wuffs_tga__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
10305 }
10306
10307 inline wuffs_base__status
10308 decode_image_config(
10309 wuffs_base__image_config* a_dst,
10310 wuffs_base__io_buffer* a_src) {
10311 return wuffs_tga__decoder__decode_image_config(this, a_dst, a_src);
10312 }
10313
10314 inline wuffs_base__status
10315 decode_frame_config(
10316 wuffs_base__frame_config* a_dst,
10317 wuffs_base__io_buffer* a_src) {
10318 return wuffs_tga__decoder__decode_frame_config(this, a_dst, a_src);
10319 }
10320
10321 inline wuffs_base__status
10322 decode_frame(
10323 wuffs_base__pixel_buffer* a_dst,
10324 wuffs_base__io_buffer* a_src,
10325 wuffs_base__pixel_blend a_blend,
10326 wuffs_base__slice_u8 a_workbuf,
10327 wuffs_base__decode_frame_options* a_opts) {
10328 return wuffs_tga__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
10329 }
10330
10331 inline wuffs_base__rect_ie_u32
10332 frame_dirty_rect() const {
10333 return wuffs_tga__decoder__frame_dirty_rect(this);
10334 }
10335
10336 inline uint32_t
10337 num_animation_loops() const {
10338 return wuffs_tga__decoder__num_animation_loops(this);
10339 }
10340
10341 inline uint64_t
10342 num_decoded_frame_configs() const {
10343 return wuffs_tga__decoder__num_decoded_frame_configs(this);
10344 }
10345
10346 inline uint64_t
10347 num_decoded_frames() const {
10348 return wuffs_tga__decoder__num_decoded_frames(this);
10349 }
10350
10351 inline wuffs_base__status
10352 restart_frame(
10353 uint64_t a_index,
10354 uint64_t a_io_position) {
10355 return wuffs_tga__decoder__restart_frame(this, a_index, a_io_position);
10356 }
10357
10358 inline wuffs_base__empty_struct
10359 set_report_metadata(
10360 uint32_t a_fourcc,
10361 bool a_report) {
10362 return wuffs_tga__decoder__set_report_metadata(this, a_fourcc, a_report);
10363 }
10364
10365 inline wuffs_base__status
10366 tell_me_more(
10367 wuffs_base__io_buffer* a_dst,
10368 wuffs_base__more_information* a_minfo,
10369 wuffs_base__io_buffer* a_src) {
10370 return wuffs_tga__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
10371 }
10372
10373 inline wuffs_base__range_ii_u64
10374 workbuf_len() const {
10375 return wuffs_tga__decoder__workbuf_len(this);
10376 }
10377
10378#endif // __cplusplus
10379}; // struct wuffs_tga__decoder__struct
10380
10381#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
10382
Nigel Taofe9d08f2022-10-28 17:30:51 +110010383#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA) || defined(WUFFS_NONMONOLITHIC)
10384
10385#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC)
10386
Nigel Taocc74cb42022-01-19 11:06:15 +110010387// ---------------- Status Codes
10388
Nigel Taoe360a532021-04-05 22:47:03 +100010389extern const char wuffs_wbmp__error__bad_header[];
10390
10391// ---------------- Public Consts
10392
10393#define WUFFS_WBMP__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE 0
10394
10395// ---------------- Struct Declarations
10396
10397typedef struct wuffs_wbmp__decoder__struct wuffs_wbmp__decoder;
10398
10399#ifdef __cplusplus
10400extern "C" {
10401#endif
10402
10403// ---------------- Public Initializer Prototypes
10404
10405// For any given "wuffs_foo__bar* self", "wuffs_foo__bar__initialize(self,
10406// etc)" should be called before any other "wuffs_foo__bar__xxx(self, etc)".
10407//
10408// Pass sizeof(*self) and WUFFS_VERSION for sizeof_star_self and wuffs_version.
10409// Pass 0 (or some combination of WUFFS_INITIALIZE__XXX) for options.
10410
10411wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
10412wuffs_wbmp__decoder__initialize(
10413 wuffs_wbmp__decoder* self,
10414 size_t sizeof_star_self,
10415 uint64_t wuffs_version,
10416 uint32_t options);
10417
10418size_t
10419sizeof__wuffs_wbmp__decoder();
10420
10421// ---------------- Allocs
10422
10423// These functions allocate and initialize Wuffs structs. They return NULL if
10424// memory allocation fails. If they return non-NULL, there is no need to call
10425// wuffs_foo__bar__initialize, but the caller is responsible for eventually
10426// calling free on the returned pointer. That pointer is effectively a C++
10427// std::unique_ptr<T, decltype(&free)>.
10428
10429wuffs_wbmp__decoder*
10430wuffs_wbmp__decoder__alloc();
10431
10432static inline wuffs_base__image_decoder*
10433wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder() {
10434 return (wuffs_base__image_decoder*)(wuffs_wbmp__decoder__alloc());
10435}
10436
10437// ---------------- Upcasts
10438
10439static inline wuffs_base__image_decoder*
10440wuffs_wbmp__decoder__upcast_as__wuffs_base__image_decoder(
10441 wuffs_wbmp__decoder* p) {
10442 return (wuffs_base__image_decoder*)p;
10443}
10444
10445// ---------------- Public Function Prototypes
10446
10447WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
10448wuffs_wbmp__decoder__set_quirk_enabled(
10449 wuffs_wbmp__decoder* self,
10450 uint32_t a_quirk,
10451 bool a_enabled);
10452
10453WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10454wuffs_wbmp__decoder__decode_image_config(
10455 wuffs_wbmp__decoder* self,
10456 wuffs_base__image_config* a_dst,
10457 wuffs_base__io_buffer* a_src);
10458
10459WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10460wuffs_wbmp__decoder__decode_frame_config(
10461 wuffs_wbmp__decoder* self,
10462 wuffs_base__frame_config* a_dst,
10463 wuffs_base__io_buffer* a_src);
10464
10465WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10466wuffs_wbmp__decoder__decode_frame(
10467 wuffs_wbmp__decoder* self,
10468 wuffs_base__pixel_buffer* a_dst,
10469 wuffs_base__io_buffer* a_src,
10470 wuffs_base__pixel_blend a_blend,
10471 wuffs_base__slice_u8 a_workbuf,
10472 wuffs_base__decode_frame_options* a_opts);
10473
10474WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
10475wuffs_wbmp__decoder__frame_dirty_rect(
10476 const wuffs_wbmp__decoder* self);
10477
10478WUFFS_BASE__MAYBE_STATIC uint32_t
10479wuffs_wbmp__decoder__num_animation_loops(
10480 const wuffs_wbmp__decoder* self);
10481
10482WUFFS_BASE__MAYBE_STATIC uint64_t
10483wuffs_wbmp__decoder__num_decoded_frame_configs(
10484 const wuffs_wbmp__decoder* self);
10485
10486WUFFS_BASE__MAYBE_STATIC uint64_t
10487wuffs_wbmp__decoder__num_decoded_frames(
10488 const wuffs_wbmp__decoder* self);
10489
10490WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10491wuffs_wbmp__decoder__restart_frame(
10492 wuffs_wbmp__decoder* self,
10493 uint64_t a_index,
10494 uint64_t a_io_position);
10495
10496WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
10497wuffs_wbmp__decoder__set_report_metadata(
10498 wuffs_wbmp__decoder* self,
10499 uint32_t a_fourcc,
10500 bool a_report);
10501
10502WUFFS_BASE__MAYBE_STATIC wuffs_base__status
10503wuffs_wbmp__decoder__tell_me_more(
10504 wuffs_wbmp__decoder* self,
10505 wuffs_base__io_buffer* a_dst,
10506 wuffs_base__more_information* a_minfo,
10507 wuffs_base__io_buffer* a_src);
10508
10509WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
10510wuffs_wbmp__decoder__workbuf_len(
10511 const wuffs_wbmp__decoder* self);
10512
10513#ifdef __cplusplus
10514} // extern "C"
10515#endif
10516
10517// ---------------- Struct Definitions
10518
10519// These structs' fields, and the sizeof them, are private implementation
10520// details that aren't guaranteed to be stable across Wuffs versions.
10521//
10522// See https://en.wikipedia.org/wiki/Opaque_pointer#C
10523
10524#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
10525
10526struct wuffs_wbmp__decoder__struct {
10527 // Do not access the private_impl's or private_data's fields directly. There
10528 // is no API/ABI compatibility or safety guarantee if you do so. Instead, use
10529 // the wuffs_foo__bar__baz functions.
10530 //
10531 // It is a struct, not a struct*, so that the outermost wuffs_foo__bar struct
10532 // can be stack allocated when WUFFS_IMPLEMENTATION is defined.
10533
10534 struct {
10535 uint32_t magic;
10536 uint32_t active_coroutine;
10537 wuffs_base__vtable vtable_for__wuffs_base__image_decoder;
10538 wuffs_base__vtable null_vtable;
10539
10540 uint32_t f_width;
10541 uint32_t f_height;
10542 uint8_t f_call_sequence;
10543 uint64_t f_frame_config_io_position;
10544 wuffs_base__pixel_swizzler f_swizzler;
10545
10546 uint32_t p_decode_image_config[1];
10547 uint32_t p_decode_frame_config[1];
10548 uint32_t p_decode_frame[1];
10549 } private_impl;
10550
10551 struct {
10552 struct {
10553 uint32_t v_i;
10554 uint32_t v_x32;
10555 } s_decode_image_config[1];
10556 struct {
10557 uint64_t v_dst_bytes_per_pixel;
10558 uint32_t v_dst_x;
10559 uint32_t v_dst_y;
10560 uint8_t v_src[1];
10561 uint8_t v_c;
10562 } s_decode_frame[1];
10563 } private_data;
10564
10565#ifdef __cplusplus
10566#if defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10567 using unique_ptr = std::unique_ptr<wuffs_wbmp__decoder, decltype(&free)>;
10568
10569 // On failure, the alloc_etc functions return nullptr. They don't throw.
10570
10571 static inline unique_ptr
10572 alloc() {
10573 return unique_ptr(wuffs_wbmp__decoder__alloc(), &free);
10574 }
10575
10576 static inline wuffs_base__image_decoder::unique_ptr
10577 alloc_as__wuffs_base__image_decoder() {
10578 return wuffs_base__image_decoder::unique_ptr(
10579 wuffs_wbmp__decoder__alloc_as__wuffs_base__image_decoder(), &free);
10580 }
10581#endif // defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10582
10583#if defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
10584 // Disallow constructing or copying an object via standard C++ mechanisms,
10585 // e.g. the "new" operator, as this struct is intentionally opaque. Its total
10586 // size and field layout is not part of the public, stable, memory-safe API.
10587 // Use malloc or memcpy and the sizeof__wuffs_foo__bar function instead, and
10588 // call wuffs_foo__bar__baz methods (which all take a "this"-like pointer as
10589 // their first argument) rather than tweaking bar.private_impl.qux fields.
10590 //
10591 // In C, we can just leave wuffs_foo__bar as an incomplete type (unless
10592 // WUFFS_IMPLEMENTATION is #define'd). In C++, we define a complete type in
10593 // order to provide convenience methods. These forward on "this", so that you
10594 // can write "bar->baz(etc)" instead of "wuffs_foo__bar__baz(bar, etc)".
10595 wuffs_wbmp__decoder__struct() = delete;
10596 wuffs_wbmp__decoder__struct(const wuffs_wbmp__decoder__struct&) = delete;
10597 wuffs_wbmp__decoder__struct& operator=(
10598 const wuffs_wbmp__decoder__struct&) = delete;
10599#endif // defined(WUFFS_BASE__HAVE_EQ_DELETE) && !defined(WUFFS_IMPLEMENTATION)
10600
10601#if !defined(WUFFS_IMPLEMENTATION)
10602 // As above, the size of the struct is not part of the public API, and unless
10603 // WUFFS_IMPLEMENTATION is #define'd, this struct type T should be heap
10604 // allocated, not stack allocated. Its size is not intended to be known at
10605 // compile time, but it is unfortunately divulged as a side effect of
10606 // defining C++ convenience methods. Use "sizeof__T()", calling the function,
10607 // instead of "sizeof T", invoking the operator. To make the two values
10608 // different, so that passing the latter will be rejected by the initialize
10609 // function, we add an arbitrary amount of dead weight.
10610 uint8_t dead_weight[123000000]; // 123 MB.
10611#endif // !defined(WUFFS_IMPLEMENTATION)
10612
10613 inline wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
10614 initialize(
10615 size_t sizeof_star_self,
10616 uint64_t wuffs_version,
10617 uint32_t options) {
10618 return wuffs_wbmp__decoder__initialize(
10619 this, sizeof_star_self, wuffs_version, options);
10620 }
10621
10622 inline wuffs_base__image_decoder*
10623 upcast_as__wuffs_base__image_decoder() {
10624 return (wuffs_base__image_decoder*)this;
10625 }
10626
10627 inline wuffs_base__empty_struct
10628 set_quirk_enabled(
10629 uint32_t a_quirk,
10630 bool a_enabled) {
10631 return wuffs_wbmp__decoder__set_quirk_enabled(this, a_quirk, a_enabled);
10632 }
10633
10634 inline wuffs_base__status
10635 decode_image_config(
10636 wuffs_base__image_config* a_dst,
10637 wuffs_base__io_buffer* a_src) {
10638 return wuffs_wbmp__decoder__decode_image_config(this, a_dst, a_src);
10639 }
10640
10641 inline wuffs_base__status
10642 decode_frame_config(
10643 wuffs_base__frame_config* a_dst,
10644 wuffs_base__io_buffer* a_src) {
10645 return wuffs_wbmp__decoder__decode_frame_config(this, a_dst, a_src);
10646 }
10647
10648 inline wuffs_base__status
10649 decode_frame(
10650 wuffs_base__pixel_buffer* a_dst,
10651 wuffs_base__io_buffer* a_src,
10652 wuffs_base__pixel_blend a_blend,
10653 wuffs_base__slice_u8 a_workbuf,
10654 wuffs_base__decode_frame_options* a_opts) {
10655 return wuffs_wbmp__decoder__decode_frame(this, a_dst, a_src, a_blend, a_workbuf, a_opts);
10656 }
10657
10658 inline wuffs_base__rect_ie_u32
10659 frame_dirty_rect() const {
10660 return wuffs_wbmp__decoder__frame_dirty_rect(this);
10661 }
10662
10663 inline uint32_t
10664 num_animation_loops() const {
10665 return wuffs_wbmp__decoder__num_animation_loops(this);
10666 }
10667
10668 inline uint64_t
10669 num_decoded_frame_configs() const {
10670 return wuffs_wbmp__decoder__num_decoded_frame_configs(this);
10671 }
10672
10673 inline uint64_t
10674 num_decoded_frames() const {
10675 return wuffs_wbmp__decoder__num_decoded_frames(this);
10676 }
10677
10678 inline wuffs_base__status
10679 restart_frame(
10680 uint64_t a_index,
10681 uint64_t a_io_position) {
10682 return wuffs_wbmp__decoder__restart_frame(this, a_index, a_io_position);
10683 }
10684
10685 inline wuffs_base__empty_struct
10686 set_report_metadata(
10687 uint32_t a_fourcc,
10688 bool a_report) {
10689 return wuffs_wbmp__decoder__set_report_metadata(this, a_fourcc, a_report);
10690 }
10691
10692 inline wuffs_base__status
10693 tell_me_more(
10694 wuffs_base__io_buffer* a_dst,
10695 wuffs_base__more_information* a_minfo,
10696 wuffs_base__io_buffer* a_src) {
10697 return wuffs_wbmp__decoder__tell_me_more(this, a_dst, a_minfo, a_src);
10698 }
10699
10700 inline wuffs_base__range_ii_u64
10701 workbuf_len() const {
10702 return wuffs_wbmp__decoder__workbuf_len(this);
10703 }
10704
10705#endif // __cplusplus
10706}; // struct wuffs_wbmp__decoder__struct
10707
10708#endif // defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)
10709
Nigel Taofe9d08f2022-10-28 17:30:51 +110010710#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP) || defined(WUFFS_NONMONOLITHIC)
10711
Nigel Taoe360a532021-04-05 22:47:03 +100010712#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
10713
10714// ---------------- Auxiliary - Base
10715
10716// Auxiliary code is discussed at
10717// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md
10718
10719#include <stdio.h>
10720
10721#include <string>
10722
10723namespace wuffs_aux {
10724
10725using IOBuffer = wuffs_base__io_buffer;
10726
10727// MemOwner represents ownership of some memory. Dynamically allocated memory
10728// (e.g. from malloc or new) is typically paired with free or delete, invoked
10729// when the std::unique_ptr is destroyed. Statically allocated memory might use
10730// MemOwner(nullptr, &free), even if that statically allocated memory is not
10731// nullptr, since calling free(nullptr) is a no-op.
10732using MemOwner = std::unique_ptr<void, decltype(&free)>;
10733
10734namespace sync_io {
10735
10736// --------
10737
Nigel Taobf9dab32021-11-18 19:19:55 +110010738// DynIOBuffer is an IOBuffer that is backed by a dynamically sized byte array.
10739// It owns that backing array and will free it in its destructor.
10740//
10741// The array size can be explicitly extended (by calling the grow method) but,
10742// unlike a C++ std::vector, there is no implicit extension (e.g. by calling
10743// std::vector::insert) and its maximum size is capped by the max_incl
10744// constructor argument.
10745//
10746// It contains an IOBuffer-typed field whose reader side provides access to
10747// previously written bytes and whose writer side provides access to the
10748// allocated but not-yet-written-to slack space. For Go programmers, this slack
10749// space is roughly analogous to the s[len(s):cap(s)] space of a slice s.
10750class DynIOBuffer {
10751 public:
10752 enum GrowResult {
10753 OK = 0,
10754 FailedMaxInclExceeded = 1,
10755 FailedOutOfMemory = 2,
10756 };
10757
10758 // m_buf holds the dynamically sized byte array and its read/write indexes:
10759 // - m_buf.meta.wi is roughly analogous to a Go slice's length.
10760 // - m_buf.data.len is roughly analogous to a Go slice's capacity. It is
10761 // also equal to the m_buf.data.ptr malloc/realloc size.
10762 //
10763 // Users should not modify the m_buf.data.ptr or m_buf.data.len fields (as
10764 // they are conceptually private to this class), but they can modify the
10765 // bytes referenced by that pointer-length pair (e.g. compactions).
10766 IOBuffer m_buf;
10767
10768 // m_max_incl is an inclusive upper bound on the backing array size.
10769 const uint64_t m_max_incl;
10770
10771 // Constructor and destructor.
10772 explicit DynIOBuffer(uint64_t max_incl);
10773 ~DynIOBuffer();
10774
10775 // Drop frees the byte array and resets m_buf. The DynIOBuffer can still be
10776 // used after a drop call. It just restarts from zero.
10777 void drop();
10778
10779 // grow ensures that the byte array size is at least min_incl and at most
10780 // max_incl. It returns FailedMaxInclExceeded if that would require
10781 // allocating more than max_incl bytes, including the case where (min_incl >
10782 // max_incl). It returns FailedOutOfMemory if memory allocation failed.
10783 GrowResult grow(uint64_t min_incl);
10784
10785 private:
10786 // Delete the copy and assign constructors.
10787 DynIOBuffer(const DynIOBuffer&) = delete;
10788 DynIOBuffer& operator=(const DynIOBuffer&) = delete;
10789
10790 static uint64_t round_up(uint64_t min_incl, uint64_t max_incl);
10791};
10792
10793// --------
10794
Nigel Taoe360a532021-04-05 22:47:03 +100010795class Input {
10796 public:
10797 virtual ~Input();
10798
10799 virtual IOBuffer* BringsItsOwnIOBuffer();
10800 virtual std::string CopyIn(IOBuffer* dst) = 0;
10801};
10802
10803// --------
10804
10805// FileInput is an Input that reads from a file source.
10806//
10807// It does not take responsibility for closing the file when done.
10808class FileInput : public Input {
10809 public:
10810 FileInput(FILE* f);
10811
10812 virtual std::string CopyIn(IOBuffer* dst);
10813
10814 private:
10815 FILE* m_f;
10816
10817 // Delete the copy and assign constructors.
10818 FileInput(const FileInput&) = delete;
10819 FileInput& operator=(const FileInput&) = delete;
10820};
10821
10822// --------
10823
10824// MemoryInput is an Input that reads from an in-memory source.
10825//
10826// It does not take responsibility for freeing the memory when done.
10827class MemoryInput : public Input {
10828 public:
10829 MemoryInput(const char* ptr, size_t len);
10830 MemoryInput(const uint8_t* ptr, size_t len);
10831
10832 virtual IOBuffer* BringsItsOwnIOBuffer();
10833 virtual std::string CopyIn(IOBuffer* dst);
10834
10835 private:
10836 IOBuffer m_io;
10837
10838 // Delete the copy and assign constructors.
10839 MemoryInput(const MemoryInput&) = delete;
10840 MemoryInput& operator=(const MemoryInput&) = delete;
10841};
10842
10843// --------
10844
10845} // namespace sync_io
10846
10847} // namespace wuffs_aux
10848
10849// ---------------- Auxiliary - CBOR
10850
10851namespace wuffs_aux {
10852
10853struct DecodeCborResult {
10854 DecodeCborResult(std::string&& error_message0, uint64_t cursor_position0);
10855
10856 std::string error_message;
10857 uint64_t cursor_position;
10858};
10859
10860class DecodeCborCallbacks {
10861 public:
10862 virtual ~DecodeCborCallbacks();
10863
10864 // AppendXxx are called for leaf nodes: literals, numbers, strings, etc.
10865
10866 virtual std::string AppendNull() = 0;
10867 virtual std::string AppendUndefined() = 0;
10868 virtual std::string AppendBool(bool val) = 0;
10869 virtual std::string AppendF64(double val) = 0;
10870 virtual std::string AppendI64(int64_t val) = 0;
10871 virtual std::string AppendU64(uint64_t val) = 0;
10872 virtual std::string AppendByteString(std::string&& val) = 0;
10873 virtual std::string AppendTextString(std::string&& val) = 0;
10874 virtual std::string AppendMinus1MinusX(uint64_t val) = 0;
10875 virtual std::string AppendCborSimpleValue(uint8_t val) = 0;
10876 virtual std::string AppendCborTag(uint64_t val) = 0;
10877
10878 // Push and Pop are called for container nodes: CBOR arrays (lists) and CBOR
10879 // maps (dictionaries).
10880 //
10881 // The flags bits combine exactly one of:
10882 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
10883 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
10884 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
10885 // and exactly one of:
10886 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
10887 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
10888 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
10889
10890 virtual std::string Push(uint32_t flags) = 0;
10891 virtual std::string Pop(uint32_t flags) = 0;
10892
10893 // Done is always the last Callback method called by DecodeCbor, whether or
10894 // not parsing the input as CBOR encountered an error. Even when successful,
10895 // trailing data may remain in input and buffer.
10896 //
10897 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
10898 // as DecodeCbor may then de-allocate the backing array.
10899 //
10900 // The default Done implementation is a no-op.
10901 virtual void //
10902 Done(DecodeCborResult& result, sync_io::Input& input, IOBuffer& buffer);
10903};
10904
Nigel Taobf9dab32021-11-18 19:19:55 +110010905// The FooArgBar types add structure to Foo's optional arguments. They wrap
10906// inner representations for several reasons:
10907// - It provides a home for the DefaultValue static method, for Foo callers
10908// that want to override some but not all optional arguments.
10909// - It provides the "Bar" name at Foo call sites, which can help self-
10910// document Foo calls with many arguemnts.
10911// - It provides some type safety against accidentally transposing or omitting
10912// adjacent fundamentally-numeric-typed optional arguments.
10913
10914// DecodeCborArgQuirks wraps an optional argument to DecodeCbor.
10915struct DecodeCborArgQuirks {
10916 explicit DecodeCborArgQuirks(wuffs_base__slice_u32 repr0);
10917 explicit DecodeCborArgQuirks(uint32_t* ptr, size_t len);
10918
10919 // DefaultValue returns an empty slice.
10920 static DecodeCborArgQuirks DefaultValue();
10921
10922 wuffs_base__slice_u32 repr;
10923};
10924
Nigel Taoe360a532021-04-05 22:47:03 +100010925// DecodeCbor calls callbacks based on the CBOR-formatted data in input.
10926//
10927// On success, the returned error_message is empty and cursor_position counts
10928// the number of bytes consumed. On failure, error_message is non-empty and
10929// cursor_position is the location of the error. That error may be a content
10930// error (invalid CBOR) or an input error (e.g. network failure).
10931DecodeCborResult //
10932DecodeCbor(DecodeCborCallbacks& callbacks,
10933 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110010934 DecodeCborArgQuirks quirks = DecodeCborArgQuirks::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100010935
10936} // namespace wuffs_aux
10937
10938// ---------------- Auxiliary - Image
10939
10940namespace wuffs_aux {
10941
10942struct DecodeImageResult {
10943 DecodeImageResult(MemOwner&& pixbuf_mem_owner0,
10944 wuffs_base__pixel_buffer pixbuf0,
10945 std::string&& error_message0);
10946 DecodeImageResult(std::string&& error_message0);
10947
10948 MemOwner pixbuf_mem_owner;
10949 wuffs_base__pixel_buffer pixbuf;
10950 std::string error_message;
10951};
10952
10953// DecodeImageCallbacks are the callbacks given to DecodeImage. They are always
10954// called in this order:
10955// 1. SelectDecoder
Nigel Taobf9dab32021-11-18 19:19:55 +110010956// 2. HandleMetadata
10957// 3. SelectPixfmt
10958// 4. AllocPixbuf
10959// 5. AllocWorkbuf
10960// 6. Done
Nigel Taoe360a532021-04-05 22:47:03 +100010961//
10962// It may return early - the third callback might not be invoked if the second
10963// one fails - but the final callback (Done) is always invoked.
10964class DecodeImageCallbacks {
10965 public:
10966 // AllocPixbufResult holds a memory allocation (the result of malloc or new,
10967 // a statically allocated pointer, etc), or an error message. The memory is
10968 // de-allocated when mem_owner goes out of scope and is destroyed.
10969 struct AllocPixbufResult {
10970 AllocPixbufResult(MemOwner&& mem_owner0, wuffs_base__pixel_buffer pixbuf0);
10971 AllocPixbufResult(std::string&& error_message0);
10972
10973 MemOwner mem_owner;
10974 wuffs_base__pixel_buffer pixbuf;
10975 std::string error_message;
10976 };
10977
10978 // AllocWorkbufResult holds a memory allocation (the result of malloc or new,
10979 // a statically allocated pointer, etc), or an error message. The memory is
10980 // de-allocated when mem_owner goes out of scope and is destroyed.
10981 struct AllocWorkbufResult {
10982 AllocWorkbufResult(MemOwner&& mem_owner0, wuffs_base__slice_u8 workbuf0);
10983 AllocWorkbufResult(std::string&& error_message0);
10984
10985 MemOwner mem_owner;
10986 wuffs_base__slice_u8 workbuf;
10987 std::string error_message;
10988 };
10989
10990 virtual ~DecodeImageCallbacks();
10991
10992 // SelectDecoder returns the image decoder for the input data's file format.
10993 // Returning a nullptr means failure (DecodeImage_UnsupportedImageFormat).
10994 //
10995 // Common formats will have a FourCC value in the range [1 ..= 0x7FFF_FFFF],
Nigel Taocc74cb42022-01-19 11:06:15 +110010996 // such as WUFFS_BASE__FOURCC__JPEG. A zero FourCC value means that Wuffs'
10997 // standard library did not recognize the image format but if SelectDecoder
10998 // was overridden, it may examine the input data's starting bytes and still
10999 // provide its own image decoder, e.g. for an exotic image file format that's
11000 // not in Wuffs' standard library. The prefix_etc fields have the same
11001 // meaning as wuffs_base__magic_number_guess_fourcc arguments. SelectDecoder
11002 // implementations should not modify prefix_data's contents.
Nigel Taoe360a532021-04-05 22:47:03 +100011003 //
11004 // SelectDecoder might be called more than once, since some image file
11005 // formats can wrap others. For example, a nominal BMP file can actually
11006 // contain a JPEG or a PNG.
11007 //
11008 // The default SelectDecoder accepts the FOURCC codes listed below. For
11009 // modular builds (i.e. when #define'ing WUFFS_CONFIG__MODULES), acceptance
11010 // of the ETC file format is optional (for each value of ETC) and depends on
11011 // the corresponding module to be enabled at compile time (i.e. #define'ing
11012 // WUFFS_CONFIG__MODULE__ETC).
11013 // - WUFFS_BASE__FOURCC__BMP
11014 // - WUFFS_BASE__FOURCC__GIF
11015 // - WUFFS_BASE__FOURCC__NIE
11016 // - WUFFS_BASE__FOURCC__PNG
Nigel Taocc74cb42022-01-19 11:06:15 +110011017 // - WUFFS_BASE__FOURCC__TGA
Nigel Taoe360a532021-04-05 22:47:03 +100011018 // - WUFFS_BASE__FOURCC__WBMP
11019 virtual wuffs_base__image_decoder::unique_ptr //
Nigel Taocc74cb42022-01-19 11:06:15 +110011020 SelectDecoder(uint32_t fourcc,
11021 wuffs_base__slice_u8 prefix_data,
11022 bool prefix_closed);
Nigel Taoe360a532021-04-05 22:47:03 +100011023
Nigel Taobf9dab32021-11-18 19:19:55 +110011024 // HandleMetadata acknowledges image metadata. minfo.flavor will be one of:
11025 // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH
11026 // - WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED
11027 // If it is ETC__METADATA_RAW_ETC then raw contains the metadata bytes. Those
11028 // bytes should not be retained beyond the the HandleMetadata call.
11029 //
11030 // minfo.metadata__fourcc() will typically match one of the
11031 // DecodeImageArgFlags bits. For example, if (REPORT_METADATA_CHRM |
11032 // REPORT_METADATA_GAMA) was passed to DecodeImage then the metadata FourCC
11033 // will be either WUFFS_BASE__FOURCC__CHRM or WUFFS_BASE__FOURCC__GAMA.
11034 //
11035 // It returns an error message, or an empty string on success.
11036 virtual std::string //
11037 HandleMetadata(const wuffs_base__more_information& minfo,
11038 wuffs_base__slice_u8 raw);
11039
Nigel Taoe360a532021-04-05 22:47:03 +100011040 // SelectPixfmt returns the destination pixel format for AllocPixbuf. It
11041 // should return wuffs_base__make_pixel_format(etc) called with one of:
11042 // - WUFFS_BASE__PIXEL_FORMAT__BGR_565
11043 // - WUFFS_BASE__PIXEL_FORMAT__BGR
11044 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL
11045 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE
11046 // - WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL
11047 // - WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL
11048 // - WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL
11049 // or return image_config.pixcfg.pixel_format(). The latter means to use the
11050 // image file's natural pixel format. For example, GIF images' natural pixel
11051 // format is an indexed one.
11052 //
11053 // Returning otherwise means failure (DecodeImage_UnsupportedPixelFormat).
11054 //
11055 // The default SelectPixfmt implementation returns
11056 // wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL) which
11057 // is 4 bytes per pixel (8 bits per channel × 4 channels).
11058 virtual wuffs_base__pixel_format //
11059 SelectPixfmt(const wuffs_base__image_config& image_config);
11060
11061 // AllocPixbuf allocates the pixel buffer.
11062 //
11063 // allow_uninitialized_memory will be true if a valid background_color was
11064 // passed to DecodeImage, since the pixel buffer's contents will be
11065 // overwritten with that color after AllocPixbuf returns.
11066 //
11067 // The default AllocPixbuf implementation allocates either uninitialized or
11068 // zeroed memory. Zeroed memory typically corresponds to filling with opaque
11069 // black or transparent black, depending on the pixel format.
11070 virtual AllocPixbufResult //
11071 AllocPixbuf(const wuffs_base__image_config& image_config,
11072 bool allow_uninitialized_memory);
11073
11074 // AllocWorkbuf allocates the work buffer. The allocated buffer's length
11075 // should be at least len_range.min_incl, but larger allocations (up to
11076 // len_range.max_incl) may have better performance (by using more memory).
11077 //
11078 // The default AllocWorkbuf implementation allocates len_range.max_incl bytes
11079 // of either uninitialized or zeroed memory.
11080 virtual AllocWorkbufResult //
11081 AllocWorkbuf(wuffs_base__range_ii_u64 len_range,
11082 bool allow_uninitialized_memory);
11083
11084 // Done is always the last Callback method called by DecodeImage, whether or
11085 // not parsing the input encountered an error. Even when successful, trailing
11086 // data may remain in input and buffer.
11087 //
11088 // The image_decoder is the one returned by SelectDecoder (if SelectDecoder
11089 // was successful), or a no-op unique_ptr otherwise. Like any unique_ptr,
11090 // ownership moves to the Done implementation.
11091 //
11092 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
11093 // as DecodeImage may then de-allocate the backing array.
11094 //
11095 // The default Done implementation is a no-op, other than running the
11096 // image_decoder unique_ptr destructor.
11097 virtual void //
11098 Done(DecodeImageResult& result,
11099 sync_io::Input& input,
11100 IOBuffer& buffer,
11101 wuffs_base__image_decoder::unique_ptr image_decoder);
11102};
11103
11104extern const char DecodeImage_BufferIsTooShort[];
11105extern const char DecodeImage_MaxInclDimensionExceeded[];
Nigel Taobf9dab32021-11-18 19:19:55 +110011106extern const char DecodeImage_MaxInclMetadataLengthExceeded[];
Nigel Taoe360a532021-04-05 22:47:03 +100011107extern const char DecodeImage_OutOfMemory[];
11108extern const char DecodeImage_UnexpectedEndOfFile[];
11109extern const char DecodeImage_UnsupportedImageFormat[];
Nigel Taobf9dab32021-11-18 19:19:55 +110011110extern const char DecodeImage_UnsupportedMetadata[];
Nigel Taoe360a532021-04-05 22:47:03 +100011111extern const char DecodeImage_UnsupportedPixelBlend[];
11112extern const char DecodeImage_UnsupportedPixelConfiguration[];
11113extern const char DecodeImage_UnsupportedPixelFormat[];
11114
Nigel Taobf9dab32021-11-18 19:19:55 +110011115// The FooArgBar types add structure to Foo's optional arguments. They wrap
11116// inner representations for several reasons:
11117// - It provides a home for the DefaultValue static method, for Foo callers
11118// that want to override some but not all optional arguments.
11119// - It provides the "Bar" name at Foo call sites, which can help self-
11120// document Foo calls with many arguemnts.
11121// - It provides some type safety against accidentally transposing or omitting
11122// adjacent fundamentally-numeric-typed optional arguments.
11123
11124// DecodeImageArgQuirks wraps an optional argument to DecodeImage.
11125struct DecodeImageArgQuirks {
11126 explicit DecodeImageArgQuirks(wuffs_base__slice_u32 repr0);
11127 explicit DecodeImageArgQuirks(uint32_t* ptr, size_t len);
11128
11129 // DefaultValue returns an empty slice.
11130 static DecodeImageArgQuirks DefaultValue();
11131
11132 wuffs_base__slice_u32 repr;
11133};
11134
11135// DecodeImageArgFlags wraps an optional argument to DecodeImage.
11136struct DecodeImageArgFlags {
11137 explicit DecodeImageArgFlags(uint64_t repr0);
11138
11139 // DefaultValue returns 0.
11140 static DecodeImageArgFlags DefaultValue();
11141
Nigel Taoebbecaa2022-01-08 14:08:27 +110011142 // TODO: support all of the REPORT_METADATA_ETC flags, not just CHRM, EXIF,
11143 // GAMA, ICCP, KVP, SRGB and XMP.
Nigel Taobf9dab32021-11-18 19:19:55 +110011144
11145 // Background Color.
11146 static constexpr uint64_t REPORT_METADATA_BGCL = 0x0001;
11147 // Primary Chromaticities and White Point.
11148 static constexpr uint64_t REPORT_METADATA_CHRM = 0x0002;
11149 // Exchangeable Image File Format.
11150 static constexpr uint64_t REPORT_METADATA_EXIF = 0x0004;
11151 // Gamma Correction.
11152 static constexpr uint64_t REPORT_METADATA_GAMA = 0x0008;
11153 // International Color Consortium Profile.
11154 static constexpr uint64_t REPORT_METADATA_ICCP = 0x0010;
11155 // Key-Value Pair.
11156 //
11157 // For PNG files, this includes iTXt, tEXt and zTXt chunks. In the
11158 // HandleMetadata callback, the raw argument contains UTF-8 strings.
11159 static constexpr uint64_t REPORT_METADATA_KVP = 0x0020;
11160 // Modification Time.
11161 static constexpr uint64_t REPORT_METADATA_MTIM = 0x0040;
11162 // Offset (2-Dimensional).
11163 static constexpr uint64_t REPORT_METADATA_OFS2 = 0x0080;
11164 // Physical Dimensions.
11165 static constexpr uint64_t REPORT_METADATA_PHYD = 0x0100;
11166 // Standard Red Green Blue (Rendering Intent).
11167 static constexpr uint64_t REPORT_METADATA_SRGB = 0x0200;
11168 // Extensible Metadata Platform.
11169 static constexpr uint64_t REPORT_METADATA_XMP = 0x0400;
11170
11171 uint64_t repr;
11172};
11173
11174// DecodeImageArgPixelBlend wraps an optional argument to DecodeImage.
11175struct DecodeImageArgPixelBlend {
11176 explicit DecodeImageArgPixelBlend(wuffs_base__pixel_blend repr0);
11177
11178 // DefaultValue returns WUFFS_BASE__PIXEL_BLEND__SRC.
11179 static DecodeImageArgPixelBlend DefaultValue();
11180
11181 wuffs_base__pixel_blend repr;
11182};
11183
11184// DecodeImageArgBackgroundColor wraps an optional argument to DecodeImage.
11185struct DecodeImageArgBackgroundColor {
11186 explicit DecodeImageArgBackgroundColor(
11187 wuffs_base__color_u32_argb_premul repr0);
11188
11189 // DefaultValue returns 1, an invalid wuffs_base__color_u32_argb_premul.
11190 static DecodeImageArgBackgroundColor DefaultValue();
11191
11192 wuffs_base__color_u32_argb_premul repr;
11193};
11194
11195// DecodeImageArgMaxInclDimension wraps an optional argument to DecodeImage.
11196struct DecodeImageArgMaxInclDimension {
11197 explicit DecodeImageArgMaxInclDimension(uint32_t repr0);
11198
11199 // DefaultValue returns 1048575 = 0x000F_FFFF, more than 1 million pixels.
11200 static DecodeImageArgMaxInclDimension DefaultValue();
11201
11202 uint32_t repr;
11203};
11204
11205// DecodeImageArgMaxInclMetadataLength wraps an optional argument to
11206// DecodeImage.
11207struct DecodeImageArgMaxInclMetadataLength {
11208 explicit DecodeImageArgMaxInclMetadataLength(uint64_t repr0);
11209
11210 // DefaultValue returns 16777215 = 0x00FF_FFFF, one less than 16 MiB.
11211 static DecodeImageArgMaxInclMetadataLength DefaultValue();
11212
11213 uint64_t repr;
11214};
11215
Nigel Taoe360a532021-04-05 22:47:03 +100011216// DecodeImage decodes the image data in input. A variety of image file formats
11217// can be decoded, depending on what callbacks.SelectDecoder returns.
11218//
11219// For animated formats, only the first frame is returned, since the API is
11220// simpler for synchronous I/O and having DecodeImage only return when
11221// completely done, but rendering animation often involves handling other
11222// events in between animation frames. To decode multiple frames of animated
11223// images, or for asynchronous I/O (e.g. when decoding an image streamed over
11224// the network), use Wuffs' lower level C API instead of its higher level,
11225// simplified C++ API (the wuffs_aux API).
11226//
11227// The DecodeImageResult's fields depend on whether decoding succeeded:
11228// - On total success, the error_message is empty and pixbuf.pixcfg.is_valid()
11229// is true.
11230// - On partial success (e.g. the input file was truncated but we are still
11231// able to decode some of the pixels), error_message is non-empty but
11232// pixbuf.pixcfg.is_valid() is still true. It is up to the caller whether to
11233// accept or reject partial success.
11234// - On failure, the error_message is non_empty and pixbuf.pixcfg.is_valid()
11235// is false.
11236//
11237// The callbacks allocate the pixel buffer memory and work buffer memory. On
11238// success, pixel buffer memory ownership is passed to the DecodeImage caller
11239// as the returned pixbuf_mem_owner. Regardless of success or failure, the work
11240// buffer memory is deleted.
11241//
11242// The pixel_blend (one of the constants listed below) determines how to
11243// composite the decoded image over the pixel buffer's original pixels (as
11244// returned by callbacks.AllocPixbuf):
11245// - WUFFS_BASE__PIXEL_BLEND__SRC
11246// - WUFFS_BASE__PIXEL_BLEND__SRC_OVER
11247//
11248// The background_color is used to fill the pixel buffer after
11249// callbacks.AllocPixbuf returns, if it is valid in the
11250// wuffs_base__color_u32_argb_premul__is_valid sense. The default value,
11251// 0x0000_0001, is not valid since its Blue channel value (0x01) is greater
11252// than its Alpha channel value (0x00). A valid background_color will typically
11253// be overwritten when pixel_blend is WUFFS_BASE__PIXEL_BLEND__SRC, but might
11254// still be visible on partial (not total) success or when pixel_blend is
11255// WUFFS_BASE__PIXEL_BLEND__SRC_OVER and the decoded image is not fully opaque.
11256//
11257// Decoding fails (with DecodeImage_MaxInclDimensionExceeded) if the image's
Nigel Taobf9dab32021-11-18 19:19:55 +110011258// width or height is greater than max_incl_dimension or if any opted-in (via
11259// flags bits) metadata is longer than max_incl_metadata_length.
Nigel Taoe360a532021-04-05 22:47:03 +100011260DecodeImageResult //
11261DecodeImage(DecodeImageCallbacks& callbacks,
11262 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110011263 DecodeImageArgQuirks quirks = DecodeImageArgQuirks::DefaultValue(),
11264 DecodeImageArgFlags flags = DecodeImageArgFlags::DefaultValue(),
11265 DecodeImageArgPixelBlend pixel_blend =
11266 DecodeImageArgPixelBlend::DefaultValue(),
11267 DecodeImageArgBackgroundColor background_color =
11268 DecodeImageArgBackgroundColor::DefaultValue(),
11269 DecodeImageArgMaxInclDimension max_incl_dimension =
11270 DecodeImageArgMaxInclDimension::DefaultValue(),
11271 DecodeImageArgMaxInclMetadataLength max_incl_metadata_length =
11272 DecodeImageArgMaxInclMetadataLength::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100011273
11274} // namespace wuffs_aux
11275
11276// ---------------- Auxiliary - JSON
11277
11278namespace wuffs_aux {
11279
11280struct DecodeJsonResult {
11281 DecodeJsonResult(std::string&& error_message0, uint64_t cursor_position0);
11282
11283 std::string error_message;
11284 uint64_t cursor_position;
11285};
11286
11287class DecodeJsonCallbacks {
11288 public:
11289 virtual ~DecodeJsonCallbacks();
11290
11291 // AppendXxx are called for leaf nodes: literals, numbers and strings. For
11292 // strings, the Callbacks implementation is responsible for tracking map keys
11293 // versus other values.
11294
11295 virtual std::string AppendNull() = 0;
11296 virtual std::string AppendBool(bool val) = 0;
11297 virtual std::string AppendF64(double val) = 0;
11298 virtual std::string AppendI64(int64_t val) = 0;
11299 virtual std::string AppendTextString(std::string&& val) = 0;
11300
11301 // Push and Pop are called for container nodes: JSON arrays (lists) and JSON
11302 // objects (dictionaries).
11303 //
11304 // The flags bits combine exactly one of:
11305 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_NONE
11306 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_LIST
11307 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__FROM_DICT
11308 // and exactly one of:
11309 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_NONE
11310 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST
11311 // - WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_DICT
11312
11313 virtual std::string Push(uint32_t flags) = 0;
11314 virtual std::string Pop(uint32_t flags) = 0;
11315
11316 // Done is always the last Callback method called by DecodeJson, whether or
11317 // not parsing the input as JSON encountered an error. Even when successful,
11318 // trailing data may remain in input and buffer. See "Unintuitive JSON
11319 // Parsing" (https://nullprogram.com/blog/2019/12/28/) which discusses JSON
11320 // parsing and when it stops.
11321 //
11322 // Do not keep a reference to buffer or buffer.data.ptr after Done returns,
11323 // as DecodeJson may then de-allocate the backing array.
11324 //
11325 // The default Done implementation is a no-op.
11326 virtual void //
11327 Done(DecodeJsonResult& result, sync_io::Input& input, IOBuffer& buffer);
11328};
11329
11330extern const char DecodeJson_BadJsonPointer[];
11331extern const char DecodeJson_NoMatch[];
11332
Nigel Taobf9dab32021-11-18 19:19:55 +110011333// The FooArgBar types add structure to Foo's optional arguments. They wrap
11334// inner representations for several reasons:
11335// - It provides a home for the DefaultValue static method, for Foo callers
11336// that want to override some but not all optional arguments.
11337// - It provides the "Bar" name at Foo call sites, which can help self-
11338// document Foo calls with many arguemnts.
11339// - It provides some type safety against accidentally transposing or omitting
11340// adjacent fundamentally-numeric-typed optional arguments.
11341
11342// DecodeJsonArgQuirks wraps an optional argument to DecodeJson.
11343struct DecodeJsonArgQuirks {
11344 explicit DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0);
11345 explicit DecodeJsonArgQuirks(uint32_t* ptr, size_t len);
11346
11347 // DefaultValue returns an empty slice.
11348 static DecodeJsonArgQuirks DefaultValue();
11349
11350 wuffs_base__slice_u32 repr;
11351};
11352
11353// DecodeJsonArgJsonPointer wraps an optional argument to DecodeJson.
11354struct DecodeJsonArgJsonPointer {
11355 explicit DecodeJsonArgJsonPointer(std::string repr0);
11356
11357 // DefaultValue returns an empty string.
11358 static DecodeJsonArgJsonPointer DefaultValue();
11359
11360 std::string repr;
11361};
11362
Nigel Taoe360a532021-04-05 22:47:03 +100011363// DecodeJson calls callbacks based on the JSON-formatted data in input.
11364//
11365// On success, the returned error_message is empty and cursor_position counts
11366// the number of bytes consumed. On failure, error_message is non-empty and
11367// cursor_position is the location of the error. That error may be a content
11368// error (invalid JSON) or an input error (e.g. network failure).
11369//
11370// json_pointer is a query in the JSON Pointer (RFC 6901) syntax. The callbacks
11371// run for the input's sub-node that matches the query. DecodeJson_NoMatch is
11372// returned if no matching sub-node was found. The empty query matches the
11373// input's root node, consistent with JSON Pointer semantics.
11374//
11375// The JSON Pointer implementation is greedy: duplicate keys are not rejected
11376// but only the first match for each '/'-separated fragment is followed.
11377DecodeJsonResult //
11378DecodeJson(DecodeJsonCallbacks& callbacks,
11379 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110011380 DecodeJsonArgQuirks quirks = DecodeJsonArgQuirks::DefaultValue(),
11381 DecodeJsonArgJsonPointer json_pointer =
11382 DecodeJsonArgJsonPointer::DefaultValue());
Nigel Taoe360a532021-04-05 22:47:03 +100011383
11384} // namespace wuffs_aux
11385
11386#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
11387
11388// ‼ WUFFS C HEADER ENDS HERE.
11389#ifdef WUFFS_IMPLEMENTATION
11390
11391#ifdef __cplusplus
11392extern "C" {
11393#endif
11394
11395// ---------------- Fundamentals
11396
11397// WUFFS_BASE__MAGIC is a magic number to check that initializers are called.
11398// It's not foolproof, given C doesn't automatically zero memory before use,
11399// but it should catch 99.99% of cases.
11400//
11401// Its (non-zero) value is arbitrary, based on md5sum("wuffs").
11402#define WUFFS_BASE__MAGIC ((uint32_t)0x3CCB6C71)
11403
11404// WUFFS_BASE__DISABLED is a magic number to indicate that a non-recoverable
11405// error was previously encountered.
11406//
11407// Its (non-zero) value is arbitrary, based on md5sum("disabled").
11408#define WUFFS_BASE__DISABLED ((uint32_t)0x075AE3D2)
11409
Nigel Taoe360a532021-04-05 22:47:03 +100011410// Use switch cases for coroutine suspension points, similar to the technique
11411// in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
11412//
Nigel Tao5aae6d12021-07-05 21:53:02 +100011413// The implicit fallthrough is intentional.
11414//
Nigel Taoe360a532021-04-05 22:47:03 +100011415// We use trivial macros instead of an explicit assignment and case statement
11416// so that clang-format doesn't get confused by the unusual "case"s.
11417#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0 case 0:;
11418#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \
11419 coro_susp_point = n; \
Nigel Taoe360a532021-04-05 22:47:03 +100011420 case n:;
11421
11422#define WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \
11423 if (!status.repr) { \
11424 goto ok; \
11425 } else if (*status.repr != '$') { \
11426 goto exit; \
11427 } \
11428 coro_susp_point = n; \
11429 goto suspend; \
11430 case n:;
11431
Nigel Taobf9dab32021-11-18 19:19:55 +110011432// The "defined(__clang__)" isn't redundant. While vanilla clang defines
11433// __GNUC__, clang-cl (which mimics MSVC's cl.exe) does not.
11434#if defined(__GNUC__) || defined(__clang__)
Nigel Taoe360a532021-04-05 22:47:03 +100011435#define WUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1))
11436#define WUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0))
11437#else
11438#define WUFFS_BASE__LIKELY(expr) (expr)
11439#define WUFFS_BASE__UNLIKELY(expr) (expr)
11440#endif
11441
11442// --------
11443
11444static inline wuffs_base__empty_struct //
11445wuffs_base__ignore_status(wuffs_base__status z) {
11446 return wuffs_base__make_empty_struct();
11447}
11448
11449static inline wuffs_base__status //
11450wuffs_base__status__ensure_not_a_suspension(wuffs_base__status z) {
11451 if (z.repr && (*z.repr == '$')) {
11452 z.repr = wuffs_base__error__cannot_return_a_suspension;
11453 }
11454 return z;
11455}
11456
11457// --------
11458
11459// wuffs_base__iterate_total_advance returns the exclusive pointer-offset at
11460// which iteration should stop. The overall slice has length total_len, each
11461// iteration's sub-slice has length iter_len and are placed iter_advance apart.
11462//
11463// The iter_advance may not be larger than iter_len. The iter_advance may be
11464// smaller than iter_len, in which case the sub-slices will overlap.
11465//
11466// The return value r satisfies ((0 <= r) && (r <= total_len)).
11467//
11468// For example, if total_len = 15, iter_len = 5 and iter_advance = 3, there are
11469// four iterations at offsets 0, 3, 6 and 9. This function returns 12.
11470//
11471// 0123456789012345
11472// [....]
11473// [....]
11474// [....]
11475// [....]
11476// $
11477// 0123456789012345
11478//
11479// For example, if total_len = 15, iter_len = 5 and iter_advance = 5, there are
11480// three iterations at offsets 0, 5 and 10. This function returns 15.
11481//
11482// 0123456789012345
11483// [....]
11484// [....]
11485// [....]
11486// $
11487// 0123456789012345
11488static inline size_t //
11489wuffs_base__iterate_total_advance(size_t total_len,
11490 size_t iter_len,
11491 size_t iter_advance) {
11492 if (total_len >= iter_len) {
11493 size_t n = total_len - iter_len;
11494 return ((n / iter_advance) * iter_advance) + iter_advance;
11495 }
11496 return 0;
11497}
11498
11499// ---------------- Numeric Types
11500
11501extern const uint8_t wuffs_base__low_bits_mask__u8[8];
11502extern const uint16_t wuffs_base__low_bits_mask__u16[16];
11503extern const uint32_t wuffs_base__low_bits_mask__u32[32];
11504extern const uint64_t wuffs_base__low_bits_mask__u64[64];
11505
11506#define WUFFS_BASE__LOW_BITS_MASK__U8(n) (wuffs_base__low_bits_mask__u8[n])
11507#define WUFFS_BASE__LOW_BITS_MASK__U16(n) (wuffs_base__low_bits_mask__u16[n])
11508#define WUFFS_BASE__LOW_BITS_MASK__U32(n) (wuffs_base__low_bits_mask__u32[n])
11509#define WUFFS_BASE__LOW_BITS_MASK__U64(n) (wuffs_base__low_bits_mask__u64[n])
11510
11511// --------
11512
11513static inline void //
11514wuffs_base__u8__sat_add_indirect(uint8_t* x, uint8_t y) {
11515 *x = wuffs_base__u8__sat_add(*x, y);
11516}
11517
11518static inline void //
11519wuffs_base__u8__sat_sub_indirect(uint8_t* x, uint8_t y) {
11520 *x = wuffs_base__u8__sat_sub(*x, y);
11521}
11522
11523static inline void //
11524wuffs_base__u16__sat_add_indirect(uint16_t* x, uint16_t y) {
11525 *x = wuffs_base__u16__sat_add(*x, y);
11526}
11527
11528static inline void //
11529wuffs_base__u16__sat_sub_indirect(uint16_t* x, uint16_t y) {
11530 *x = wuffs_base__u16__sat_sub(*x, y);
11531}
11532
11533static inline void //
11534wuffs_base__u32__sat_add_indirect(uint32_t* x, uint32_t y) {
11535 *x = wuffs_base__u32__sat_add(*x, y);
11536}
11537
11538static inline void //
11539wuffs_base__u32__sat_sub_indirect(uint32_t* x, uint32_t y) {
11540 *x = wuffs_base__u32__sat_sub(*x, y);
11541}
11542
11543static inline void //
11544wuffs_base__u64__sat_add_indirect(uint64_t* x, uint64_t y) {
11545 *x = wuffs_base__u64__sat_add(*x, y);
11546}
11547
11548static inline void //
11549wuffs_base__u64__sat_sub_indirect(uint64_t* x, uint64_t y) {
11550 *x = wuffs_base__u64__sat_sub(*x, y);
11551}
11552
11553// ---------------- Slices and Tables
11554
11555// wuffs_base__slice_u8__prefix returns up to the first up_to bytes of s.
11556static inline wuffs_base__slice_u8 //
11557wuffs_base__slice_u8__prefix(wuffs_base__slice_u8 s, uint64_t up_to) {
11558 if (((uint64_t)(s.len)) > up_to) {
11559 s.len = ((size_t)up_to);
11560 }
11561 return s;
11562}
11563
11564// wuffs_base__slice_u8__suffix returns up to the last up_to bytes of s.
11565static inline wuffs_base__slice_u8 //
11566wuffs_base__slice_u8__suffix(wuffs_base__slice_u8 s, uint64_t up_to) {
11567 if (((uint64_t)(s.len)) > up_to) {
11568 s.ptr += ((uint64_t)(s.len)) - up_to;
11569 s.len = ((size_t)up_to);
11570 }
11571 return s;
11572}
11573
11574// wuffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr, len)
11575// where len is the minimum of dst.len and src.len.
11576//
11577// Passing a wuffs_base__slice_u8 with all fields NULL or zero (a valid, empty
11578// slice) is valid and results in a no-op.
11579static inline uint64_t //
11580wuffs_base__slice_u8__copy_from_slice(wuffs_base__slice_u8 dst,
11581 wuffs_base__slice_u8 src) {
11582 size_t len = dst.len < src.len ? dst.len : src.len;
11583 if (len > 0) {
11584 memmove(dst.ptr, src.ptr, len);
11585 }
11586 return len;
11587}
11588
11589// --------
11590
11591static inline wuffs_base__slice_u8 //
Nigel Taobf9dab32021-11-18 19:19:55 +110011592wuffs_base__table_u8__row_u32(wuffs_base__table_u8 t, uint32_t y) {
Nigel Taoe360a532021-04-05 22:47:03 +100011593 if (y < t.height) {
11594 return wuffs_base__make_slice_u8(t.ptr + (t.stride * y), t.width);
11595 }
11596 return wuffs_base__make_slice_u8(NULL, 0);
11597}
11598
11599// ---------------- Slices and Tables (Utility)
11600
11601#define wuffs_base__utility__empty_slice_u8 wuffs_base__empty_slice_u8
11602
11603// ---------------- Ranges and Rects
11604
11605static inline uint32_t //
11606wuffs_base__range_ii_u32__get_min_incl(const wuffs_base__range_ii_u32* r) {
11607 return r->min_incl;
11608}
11609
11610static inline uint32_t //
11611wuffs_base__range_ii_u32__get_max_incl(const wuffs_base__range_ii_u32* r) {
11612 return r->max_incl;
11613}
11614
11615static inline uint32_t //
11616wuffs_base__range_ie_u32__get_min_incl(const wuffs_base__range_ie_u32* r) {
11617 return r->min_incl;
11618}
11619
11620static inline uint32_t //
11621wuffs_base__range_ie_u32__get_max_excl(const wuffs_base__range_ie_u32* r) {
11622 return r->max_excl;
11623}
11624
11625static inline uint64_t //
11626wuffs_base__range_ii_u64__get_min_incl(const wuffs_base__range_ii_u64* r) {
11627 return r->min_incl;
11628}
11629
11630static inline uint64_t //
11631wuffs_base__range_ii_u64__get_max_incl(const wuffs_base__range_ii_u64* r) {
11632 return r->max_incl;
11633}
11634
11635static inline uint64_t //
11636wuffs_base__range_ie_u64__get_min_incl(const wuffs_base__range_ie_u64* r) {
11637 return r->min_incl;
11638}
11639
11640static inline uint64_t //
11641wuffs_base__range_ie_u64__get_max_excl(const wuffs_base__range_ie_u64* r) {
11642 return r->max_excl;
11643}
11644
11645// ---------------- Ranges and Rects (Utility)
11646
11647#define wuffs_base__utility__empty_range_ii_u32 wuffs_base__empty_range_ii_u32
11648#define wuffs_base__utility__empty_range_ie_u32 wuffs_base__empty_range_ie_u32
11649#define wuffs_base__utility__empty_range_ii_u64 wuffs_base__empty_range_ii_u64
11650#define wuffs_base__utility__empty_range_ie_u64 wuffs_base__empty_range_ie_u64
11651#define wuffs_base__utility__empty_rect_ii_u32 wuffs_base__empty_rect_ii_u32
11652#define wuffs_base__utility__empty_rect_ie_u32 wuffs_base__empty_rect_ie_u32
11653#define wuffs_base__utility__make_range_ii_u32 wuffs_base__make_range_ii_u32
11654#define wuffs_base__utility__make_range_ie_u32 wuffs_base__make_range_ie_u32
11655#define wuffs_base__utility__make_range_ii_u64 wuffs_base__make_range_ii_u64
11656#define wuffs_base__utility__make_range_ie_u64 wuffs_base__make_range_ie_u64
11657#define wuffs_base__utility__make_rect_ii_u32 wuffs_base__make_rect_ii_u32
11658#define wuffs_base__utility__make_rect_ie_u32 wuffs_base__make_rect_ie_u32
11659
11660// ---------------- I/O
11661
11662static inline uint64_t //
11663wuffs_base__io__count_since(uint64_t mark, uint64_t index) {
11664 if (index >= mark) {
11665 return index - mark;
11666 }
11667 return 0;
11668}
11669
11670// TODO: drop the "const" in "const uint8_t* ptr". Some though required about
11671// the base.io_reader.since method returning a mutable "slice base.u8".
11672#if defined(__GNUC__)
11673#pragma GCC diagnostic push
11674#pragma GCC diagnostic ignored "-Wcast-qual"
11675#endif
11676static inline wuffs_base__slice_u8 //
11677wuffs_base__io__since(uint64_t mark, uint64_t index, const uint8_t* ptr) {
11678 if (index >= mark) {
11679 return wuffs_base__make_slice_u8(((uint8_t*)ptr) + mark,
11680 ((size_t)(index - mark)));
11681 }
11682 return wuffs_base__make_slice_u8(NULL, 0);
11683}
11684#if defined(__GNUC__)
11685#pragma GCC diagnostic pop
11686#endif
11687
11688// --------
11689
11690static inline void //
11691wuffs_base__io_reader__limit(const uint8_t** ptr_io2_r,
11692 const uint8_t* iop_r,
11693 uint64_t limit) {
11694 if (((uint64_t)(*ptr_io2_r - iop_r)) > limit) {
11695 *ptr_io2_r = iop_r + limit;
11696 }
11697}
11698
11699static inline uint32_t //
11700wuffs_base__io_reader__limited_copy_u32_to_slice(const uint8_t** ptr_iop_r,
11701 const uint8_t* io2_r,
11702 uint32_t length,
11703 wuffs_base__slice_u8 dst) {
11704 const uint8_t* iop_r = *ptr_iop_r;
11705 size_t n = dst.len;
11706 if (n > length) {
11707 n = length;
11708 }
11709 if (n > ((size_t)(io2_r - iop_r))) {
11710 n = (size_t)(io2_r - iop_r);
11711 }
11712 if (n > 0) {
11713 memmove(dst.ptr, iop_r, n);
11714 *ptr_iop_r += n;
11715 }
11716 return (uint32_t)(n);
11717}
11718
11719// wuffs_base__io_reader__match7 returns whether the io_reader's upcoming bytes
11720// start with the given prefix (up to 7 bytes long). It is peek-like, not
11721// read-like, in that there are no side-effects.
11722//
11723// The low 3 bits of a hold the prefix length, n.
11724//
11725// The high 56 bits of a hold the prefix itself, in little-endian order. The
11726// first prefix byte is in bits 8..=15, the second prefix byte is in bits
11727// 16..=23, etc. The high (8 * (7 - n)) bits are ignored.
11728//
11729// There are three possible return values:
11730// - 0 means success.
11731// - 1 means inconclusive, equivalent to "$short read".
11732// - 2 means failure.
11733static inline uint32_t //
11734wuffs_base__io_reader__match7(const uint8_t* iop_r,
11735 const uint8_t* io2_r,
11736 wuffs_base__io_buffer* r,
11737 uint64_t a) {
11738 uint32_t n = a & 7;
11739 a >>= 8;
11740 if ((io2_r - iop_r) >= 8) {
11741 uint64_t x = wuffs_base__peek_u64le__no_bounds_check(iop_r);
11742 uint32_t shift = 8 * (8 - n);
11743 return ((a << shift) == (x << shift)) ? 0 : 2;
11744 }
11745 for (; n > 0; n--) {
11746 if (iop_r >= io2_r) {
11747 return (r && r->meta.closed) ? 2 : 1;
11748 } else if (*iop_r != ((uint8_t)(a))) {
11749 return 2;
11750 }
11751 iop_r++;
11752 a >>= 8;
11753 }
11754 return 0;
11755}
11756
11757static inline wuffs_base__io_buffer* //
11758wuffs_base__io_reader__set(wuffs_base__io_buffer* b,
11759 const uint8_t** ptr_iop_r,
11760 const uint8_t** ptr_io0_r,
11761 const uint8_t** ptr_io1_r,
11762 const uint8_t** ptr_io2_r,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100011763 wuffs_base__slice_u8 data,
11764 uint64_t history_position) {
Nigel Taoe360a532021-04-05 22:47:03 +100011765 b->data = data;
11766 b->meta.wi = data.len;
11767 b->meta.ri = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100011768 b->meta.pos = history_position;
Nigel Taoe360a532021-04-05 22:47:03 +100011769 b->meta.closed = false;
11770
11771 *ptr_iop_r = data.ptr;
11772 *ptr_io0_r = data.ptr;
11773 *ptr_io1_r = data.ptr;
11774 *ptr_io2_r = data.ptr + data.len;
11775
11776 return b;
11777}
11778
11779// --------
11780
11781static inline uint64_t //
11782wuffs_base__io_writer__copy_from_slice(uint8_t** ptr_iop_w,
11783 uint8_t* io2_w,
11784 wuffs_base__slice_u8 src) {
11785 uint8_t* iop_w = *ptr_iop_w;
11786 size_t n = src.len;
11787 if (n > ((size_t)(io2_w - iop_w))) {
11788 n = (size_t)(io2_w - iop_w);
11789 }
11790 if (n > 0) {
11791 memmove(iop_w, src.ptr, n);
11792 *ptr_iop_w += n;
11793 }
11794 return (uint64_t)(n);
11795}
11796
11797static inline void //
11798wuffs_base__io_writer__limit(uint8_t** ptr_io2_w,
11799 uint8_t* iop_w,
11800 uint64_t limit) {
11801 if (((uint64_t)(*ptr_io2_w - iop_w)) > limit) {
11802 *ptr_io2_w = iop_w + limit;
11803 }
11804}
11805
11806static inline uint32_t //
11807wuffs_base__io_writer__limited_copy_u32_from_history(uint8_t** ptr_iop_w,
Nigel Taoebbecaa2022-01-08 14:08:27 +110011808 uint8_t* io0_w,
Nigel Taoe360a532021-04-05 22:47:03 +100011809 uint8_t* io2_w,
11810 uint32_t length,
11811 uint32_t distance) {
11812 if (!distance) {
11813 return 0;
11814 }
11815 uint8_t* p = *ptr_iop_w;
Nigel Taoebbecaa2022-01-08 14:08:27 +110011816 if ((size_t)(p - io0_w) < (size_t)(distance)) {
Nigel Taoe360a532021-04-05 22:47:03 +100011817 return 0;
11818 }
11819 uint8_t* q = p - distance;
11820 size_t n = (size_t)(io2_w - p);
11821 if ((size_t)(length) > n) {
11822 length = (uint32_t)(n);
11823 } else {
11824 n = (size_t)(length);
11825 }
11826 // TODO: unrolling by 3 seems best for the std/deflate benchmarks, but that
11827 // is mostly because 3 is the minimum length for the deflate format. This
11828 // function implementation shouldn't overfit to that one format. Perhaps the
11829 // limited_copy_u32_from_history Wuffs method should also take an unroll hint
11830 // argument, and the cgen can look if that argument is the constant
11831 // expression '3'.
11832 //
11833 // See also wuffs_base__io_writer__limited_copy_u32_from_history_fast below.
11834 for (; n >= 3; n -= 3) {
11835 *p++ = *q++;
11836 *p++ = *q++;
11837 *p++ = *q++;
11838 }
11839 for (; n; n--) {
11840 *p++ = *q++;
11841 }
11842 *ptr_iop_w = p;
11843 return length;
11844}
11845
11846// wuffs_base__io_writer__limited_copy_u32_from_history_fast is like the
11847// wuffs_base__io_writer__limited_copy_u32_from_history function above, but has
11848// stronger pre-conditions.
11849//
11850// The caller needs to prove that:
11851// - length <= (io2_w - *ptr_iop_w)
11852// - distance >= 1
Nigel Taoebbecaa2022-01-08 14:08:27 +110011853// - distance <= (*ptr_iop_w - io0_w)
Nigel Taoe360a532021-04-05 22:47:03 +100011854static inline uint32_t //
11855wuffs_base__io_writer__limited_copy_u32_from_history_fast(uint8_t** ptr_iop_w,
Nigel Taoebbecaa2022-01-08 14:08:27 +110011856 uint8_t* io0_w,
Nigel Taoe360a532021-04-05 22:47:03 +100011857 uint8_t* io2_w,
11858 uint32_t length,
11859 uint32_t distance) {
11860 uint8_t* p = *ptr_iop_w;
11861 uint8_t* q = p - distance;
11862 uint32_t n = length;
11863 for (; n >= 3; n -= 3) {
11864 *p++ = *q++;
11865 *p++ = *q++;
11866 *p++ = *q++;
11867 }
11868 for (; n; n--) {
11869 *p++ = *q++;
11870 }
11871 *ptr_iop_w = p;
11872 return length;
11873}
11874
Nigel Tao5571bfe2021-06-24 22:44:29 +100011875// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast
11876// copies the previous byte (the one immediately before *ptr_iop_w), copying 8
11877// byte chunks at a time. Each chunk contains 8 repetitions of the same byte.
11878//
11879// In terms of number of bytes copied, length is rounded up to a multiple of 8.
11880// As a special case, a zero length rounds up to 8 (even though 0 is already a
11881// multiple of 8), since there is always at least one 8 byte chunk copied.
11882//
11883// In terms of advancing *ptr_iop_w, length is not rounded up.
11884//
11885// The caller needs to prove that:
11886// - (length + 8) <= (io2_w - *ptr_iop_w)
11887// - distance == 1
Nigel Taoebbecaa2022-01-08 14:08:27 +110011888// - distance <= (*ptr_iop_w - io0_w)
Nigel Tao5571bfe2021-06-24 22:44:29 +100011889static inline uint32_t //
11890wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
11891 uint8_t** ptr_iop_w,
Nigel Taoebbecaa2022-01-08 14:08:27 +110011892 uint8_t* io0_w,
Nigel Tao5571bfe2021-06-24 22:44:29 +100011893 uint8_t* io2_w,
11894 uint32_t length,
11895 uint32_t distance) {
11896 uint8_t* p = *ptr_iop_w;
11897 uint64_t x = p[-1];
11898 x |= x << 8;
11899 x |= x << 16;
11900 x |= x << 32;
11901 uint32_t n = length;
11902 while (1) {
11903 wuffs_base__poke_u64le__no_bounds_check(p, x);
11904 if (n <= 8) {
11905 p += n;
11906 break;
11907 }
11908 p += 8;
11909 n -= 8;
11910 }
11911 *ptr_iop_w = p;
11912 return length;
11913}
11914
Nigel Taoe360a532021-04-05 22:47:03 +100011915// wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast is
11916// like the wuffs_base__io_writer__limited_copy_u32_from_history_fast function
11917// above, but copies 8 byte chunks at a time.
11918//
11919// In terms of number of bytes copied, length is rounded up to a multiple of 8.
11920// As a special case, a zero length rounds up to 8 (even though 0 is already a
11921// multiple of 8), since there is always at least one 8 byte chunk copied.
11922//
11923// In terms of advancing *ptr_iop_w, length is not rounded up.
11924//
11925// The caller needs to prove that:
11926// - (length + 8) <= (io2_w - *ptr_iop_w)
11927// - distance >= 8
Nigel Taoebbecaa2022-01-08 14:08:27 +110011928// - distance <= (*ptr_iop_w - io0_w)
Nigel Taoe360a532021-04-05 22:47:03 +100011929static inline uint32_t //
11930wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
11931 uint8_t** ptr_iop_w,
Nigel Taoebbecaa2022-01-08 14:08:27 +110011932 uint8_t* io0_w,
Nigel Taoe360a532021-04-05 22:47:03 +100011933 uint8_t* io2_w,
11934 uint32_t length,
11935 uint32_t distance) {
11936 uint8_t* p = *ptr_iop_w;
11937 uint8_t* q = p - distance;
11938 uint32_t n = length;
11939 while (1) {
11940 memcpy(p, q, 8);
11941 if (n <= 8) {
11942 p += n;
11943 break;
11944 }
11945 p += 8;
11946 q += 8;
11947 n -= 8;
11948 }
11949 *ptr_iop_w = p;
11950 return length;
11951}
11952
11953static inline uint32_t //
11954wuffs_base__io_writer__limited_copy_u32_from_reader(uint8_t** ptr_iop_w,
11955 uint8_t* io2_w,
11956 uint32_t length,
11957 const uint8_t** ptr_iop_r,
11958 const uint8_t* io2_r) {
11959 uint8_t* iop_w = *ptr_iop_w;
11960 size_t n = length;
11961 if (n > ((size_t)(io2_w - iop_w))) {
11962 n = (size_t)(io2_w - iop_w);
11963 }
11964 const uint8_t* iop_r = *ptr_iop_r;
11965 if (n > ((size_t)(io2_r - iop_r))) {
11966 n = (size_t)(io2_r - iop_r);
11967 }
11968 if (n > 0) {
11969 memmove(iop_w, iop_r, n);
11970 *ptr_iop_w += n;
11971 *ptr_iop_r += n;
11972 }
11973 return (uint32_t)(n);
11974}
11975
11976static inline uint32_t //
11977wuffs_base__io_writer__limited_copy_u32_from_slice(uint8_t** ptr_iop_w,
11978 uint8_t* io2_w,
11979 uint32_t length,
11980 wuffs_base__slice_u8 src) {
11981 uint8_t* iop_w = *ptr_iop_w;
11982 size_t n = src.len;
11983 if (n > length) {
11984 n = length;
11985 }
11986 if (n > ((size_t)(io2_w - iop_w))) {
11987 n = (size_t)(io2_w - iop_w);
11988 }
11989 if (n > 0) {
11990 memmove(iop_w, src.ptr, n);
11991 *ptr_iop_w += n;
11992 }
11993 return (uint32_t)(n);
11994}
11995
11996static inline wuffs_base__io_buffer* //
11997wuffs_base__io_writer__set(wuffs_base__io_buffer* b,
11998 uint8_t** ptr_iop_w,
11999 uint8_t** ptr_io0_w,
12000 uint8_t** ptr_io1_w,
12001 uint8_t** ptr_io2_w,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100012002 wuffs_base__slice_u8 data,
12003 uint64_t history_position) {
Nigel Taoe360a532021-04-05 22:47:03 +100012004 b->data = data;
12005 b->meta.wi = 0;
12006 b->meta.ri = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100012007 b->meta.pos = history_position;
Nigel Taoe360a532021-04-05 22:47:03 +100012008 b->meta.closed = false;
12009
12010 *ptr_iop_w = data.ptr;
12011 *ptr_io0_w = data.ptr;
12012 *ptr_io1_w = data.ptr;
12013 *ptr_io2_w = data.ptr + data.len;
12014
12015 return b;
12016}
12017
12018// ---------------- I/O (Utility)
12019
12020#define wuffs_base__utility__empty_io_reader wuffs_base__empty_io_reader
12021#define wuffs_base__utility__empty_io_writer wuffs_base__empty_io_writer
12022
12023// ---------------- Tokens
12024
12025// ---------------- Tokens (Utility)
12026
12027// ---------------- Memory Allocation
12028
12029// ---------------- Images
12030
12031WUFFS_BASE__MAYBE_STATIC uint64_t //
12032wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
12033 const wuffs_base__pixel_swizzler* p,
12034 uint32_t up_to_num_pixels,
12035 wuffs_base__slice_u8 dst,
12036 wuffs_base__slice_u8 dst_palette,
12037 const uint8_t** ptr_iop_r,
12038 const uint8_t* io2_r);
12039
12040WUFFS_BASE__MAYBE_STATIC uint64_t //
12041wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
12042 const wuffs_base__pixel_swizzler* p,
12043 wuffs_base__slice_u8 dst,
12044 wuffs_base__slice_u8 dst_palette,
12045 const uint8_t** ptr_iop_r,
12046 const uint8_t* io2_r);
12047
12048WUFFS_BASE__MAYBE_STATIC uint64_t //
12049wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(
12050 const wuffs_base__pixel_swizzler* p,
12051 wuffs_base__slice_u8 dst,
12052 wuffs_base__slice_u8 dst_palette,
12053 uint64_t num_pixels);
12054
12055// ---------------- Images (Utility)
12056
12057#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format
12058
12059// ---------------- String Conversions
12060
12061// ---------------- Unicode and UTF-8
12062
12063// ----------------
12064
12065#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
12066 defined(WUFFS_CONFIG__MODULE__BASE__CORE)
12067
12068const uint8_t wuffs_base__low_bits_mask__u8[8] = {
12069 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F,
12070};
12071
12072const uint16_t wuffs_base__low_bits_mask__u16[16] = {
12073 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F,
12074 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF,
12075};
12076
12077const uint32_t wuffs_base__low_bits_mask__u32[32] = {
12078 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F,
12079 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,
12080 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF,
12081 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,
12082 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,
12083 0x3FFFFFFF, 0x7FFFFFFF,
12084};
12085
12086const uint64_t wuffs_base__low_bits_mask__u64[64] = {
12087 0x0000000000000000, 0x0000000000000001, 0x0000000000000003,
12088 0x0000000000000007, 0x000000000000000F, 0x000000000000001F,
12089 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,
12090 0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF,
12091 0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF,
12092 0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF,
12093 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,
12094 0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF,
12095 0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF,
12096 0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF,
12097 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,
12098 0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF,
12099 0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF,
12100 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF,
12101 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,
12102 0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF,
12103 0x0000FFFFFFFFFFFF, 0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF,
12104 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF,
12105 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,
12106 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,
12107 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,
12108 0x7FFFFFFFFFFFFFFF,
12109};
12110
12111const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
12112 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
12113 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
12114};
12115
12116const char wuffs_base__note__i_o_redirect[] = "@base: I/O redirect";
12117const char wuffs_base__note__end_of_data[] = "@base: end of data";
12118const char wuffs_base__note__metadata_reported[] = "@base: metadata reported";
12119const char wuffs_base__suspension__even_more_information[] = "$base: even more information";
12120const char wuffs_base__suspension__mispositioned_read[] = "$base: mispositioned read";
12121const char wuffs_base__suspension__mispositioned_write[] = "$base: mispositioned write";
12122const char wuffs_base__suspension__short_read[] = "$base: short read";
12123const char wuffs_base__suspension__short_write[] = "$base: short write";
12124const char wuffs_base__error__bad_i_o_position[] = "#base: bad I/O position";
12125const char wuffs_base__error__bad_argument_length_too_short[] = "#base: bad argument (length too short)";
12126const char wuffs_base__error__bad_argument[] = "#base: bad argument";
12127const char wuffs_base__error__bad_call_sequence[] = "#base: bad call sequence";
12128const char wuffs_base__error__bad_data[] = "#base: bad data";
12129const char wuffs_base__error__bad_receiver[] = "#base: bad receiver";
12130const char wuffs_base__error__bad_restart[] = "#base: bad restart";
12131const char wuffs_base__error__bad_sizeof_receiver[] = "#base: bad sizeof receiver";
12132const char wuffs_base__error__bad_vtable[] = "#base: bad vtable";
12133const char wuffs_base__error__bad_workbuf_length[] = "#base: bad workbuf length";
12134const char wuffs_base__error__bad_wuffs_version[] = "#base: bad wuffs version";
12135const char wuffs_base__error__cannot_return_a_suspension[] = "#base: cannot return a suspension";
12136const char wuffs_base__error__disabled_by_previous_error[] = "#base: disabled by previous error";
12137const char wuffs_base__error__initialize_falsely_claimed_already_zeroed[] = "#base: initialize falsely claimed already zeroed";
12138const char wuffs_base__error__initialize_not_called[] = "#base: initialize not called";
12139const char wuffs_base__error__interleaved_coroutine_calls[] = "#base: interleaved coroutine calls";
12140const char wuffs_base__error__no_more_information[] = "#base: no more information";
12141const char wuffs_base__error__not_enough_data[] = "#base: not enough data";
12142const char wuffs_base__error__out_of_bounds[] = "#base: out of bounds";
12143const char wuffs_base__error__unsupported_method[] = "#base: unsupported method";
12144const char wuffs_base__error__unsupported_option[] = "#base: unsupported option";
12145const char wuffs_base__error__unsupported_pixel_swizzler_option[] = "#base: unsupported pixel swizzler option";
12146const char wuffs_base__error__too_much_data[] = "#base: too much data";
12147
12148const char wuffs_base__hasher_u32__vtable_name[] = "{vtable}wuffs_base__hasher_u32";
12149const char wuffs_base__image_decoder__vtable_name[] = "{vtable}wuffs_base__image_decoder";
12150const char wuffs_base__io_transformer__vtable_name[] = "{vtable}wuffs_base__io_transformer";
12151const char wuffs_base__token_decoder__vtable_name[] = "{vtable}wuffs_base__token_decoder";
12152
12153#endif // !defined(WUFFS_CONFIG__MODULES) ||
12154 // defined(WUFFS_CONFIG__MODULE__BASE) ||
12155 // defined(WUFFS_CONFIG__MODULE__BASE__CORE)
12156
12157#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
12158 defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)
12159
12160// ---------------- Interface Definitions.
12161
12162WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
12163wuffs_base__hasher_u32__set_quirk_enabled(
12164 wuffs_base__hasher_u32* self,
12165 uint32_t a_quirk,
12166 bool a_enabled) {
12167 if (!self) {
12168 return wuffs_base__make_empty_struct();
12169 }
12170 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12171 return wuffs_base__make_empty_struct();
12172 }
12173
12174 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12175 int i;
12176 for (i = 0; i < 63; i++) {
12177 if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) {
12178 const wuffs_base__hasher_u32__func_ptrs* func_ptrs =
12179 (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers);
12180 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
12181 } else if (v->vtable_name == NULL) {
12182 break;
12183 }
12184 v++;
12185 }
12186
12187 return wuffs_base__make_empty_struct();
12188}
12189
12190WUFFS_BASE__MAYBE_STATIC uint32_t
12191wuffs_base__hasher_u32__update_u32(
12192 wuffs_base__hasher_u32* self,
12193 wuffs_base__slice_u8 a_x) {
12194 if (!self) {
12195 return 0;
12196 }
12197 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12198 return 0;
12199 }
12200
12201 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12202 int i;
12203 for (i = 0; i < 63; i++) {
12204 if (v->vtable_name == wuffs_base__hasher_u32__vtable_name) {
12205 const wuffs_base__hasher_u32__func_ptrs* func_ptrs =
12206 (const wuffs_base__hasher_u32__func_ptrs*)(v->function_pointers);
12207 return (*func_ptrs->update_u32)(self, a_x);
12208 } else if (v->vtable_name == NULL) {
12209 break;
12210 }
12211 v++;
12212 }
12213
12214 return 0;
12215}
12216
12217// --------
12218
12219WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12220wuffs_base__image_decoder__decode_frame(
12221 wuffs_base__image_decoder* self,
12222 wuffs_base__pixel_buffer* a_dst,
12223 wuffs_base__io_buffer* a_src,
12224 wuffs_base__pixel_blend a_blend,
12225 wuffs_base__slice_u8 a_workbuf,
12226 wuffs_base__decode_frame_options* a_opts) {
12227 if (!self) {
12228 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12229 }
12230 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12231 return wuffs_base__make_status(
12232 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12233 ? wuffs_base__error__disabled_by_previous_error
12234 : wuffs_base__error__initialize_not_called);
12235 }
12236
12237 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12238 int i;
12239 for (i = 0; i < 63; i++) {
12240 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12241 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12242 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12243 return (*func_ptrs->decode_frame)(self, a_dst, a_src, a_blend, a_workbuf, a_opts);
12244 } else if (v->vtable_name == NULL) {
12245 break;
12246 }
12247 v++;
12248 }
12249
12250 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12251}
12252
12253WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12254wuffs_base__image_decoder__decode_frame_config(
12255 wuffs_base__image_decoder* self,
12256 wuffs_base__frame_config* a_dst,
12257 wuffs_base__io_buffer* a_src) {
12258 if (!self) {
12259 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12260 }
12261 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12262 return wuffs_base__make_status(
12263 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12264 ? wuffs_base__error__disabled_by_previous_error
12265 : wuffs_base__error__initialize_not_called);
12266 }
12267
12268 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12269 int i;
12270 for (i = 0; i < 63; i++) {
12271 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12272 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12273 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12274 return (*func_ptrs->decode_frame_config)(self, a_dst, a_src);
12275 } else if (v->vtable_name == NULL) {
12276 break;
12277 }
12278 v++;
12279 }
12280
12281 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12282}
12283
12284WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12285wuffs_base__image_decoder__decode_image_config(
12286 wuffs_base__image_decoder* self,
12287 wuffs_base__image_config* a_dst,
12288 wuffs_base__io_buffer* a_src) {
12289 if (!self) {
12290 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12291 }
12292 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12293 return wuffs_base__make_status(
12294 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12295 ? wuffs_base__error__disabled_by_previous_error
12296 : wuffs_base__error__initialize_not_called);
12297 }
12298
12299 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12300 int i;
12301 for (i = 0; i < 63; i++) {
12302 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12303 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12304 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12305 return (*func_ptrs->decode_image_config)(self, a_dst, a_src);
12306 } else if (v->vtable_name == NULL) {
12307 break;
12308 }
12309 v++;
12310 }
12311
12312 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12313}
12314
12315WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
12316wuffs_base__image_decoder__frame_dirty_rect(
12317 const wuffs_base__image_decoder* self) {
12318 if (!self) {
12319 return wuffs_base__utility__empty_rect_ie_u32();
12320 }
12321 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12322 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12323 return wuffs_base__utility__empty_rect_ie_u32();
12324 }
12325
12326 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12327 int i;
12328 for (i = 0; i < 63; i++) {
12329 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12330 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12331 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12332 return (*func_ptrs->frame_dirty_rect)(self);
12333 } else if (v->vtable_name == NULL) {
12334 break;
12335 }
12336 v++;
12337 }
12338
12339 return wuffs_base__utility__empty_rect_ie_u32();
12340}
12341
12342WUFFS_BASE__MAYBE_STATIC uint32_t
12343wuffs_base__image_decoder__num_animation_loops(
12344 const wuffs_base__image_decoder* self) {
12345 if (!self) {
12346 return 0;
12347 }
12348 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12349 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12350 return 0;
12351 }
12352
12353 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12354 int i;
12355 for (i = 0; i < 63; i++) {
12356 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12357 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12358 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12359 return (*func_ptrs->num_animation_loops)(self);
12360 } else if (v->vtable_name == NULL) {
12361 break;
12362 }
12363 v++;
12364 }
12365
12366 return 0;
12367}
12368
12369WUFFS_BASE__MAYBE_STATIC uint64_t
12370wuffs_base__image_decoder__num_decoded_frame_configs(
12371 const wuffs_base__image_decoder* self) {
12372 if (!self) {
12373 return 0;
12374 }
12375 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12376 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12377 return 0;
12378 }
12379
12380 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12381 int i;
12382 for (i = 0; i < 63; i++) {
12383 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12384 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12385 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12386 return (*func_ptrs->num_decoded_frame_configs)(self);
12387 } else if (v->vtable_name == NULL) {
12388 break;
12389 }
12390 v++;
12391 }
12392
12393 return 0;
12394}
12395
12396WUFFS_BASE__MAYBE_STATIC uint64_t
12397wuffs_base__image_decoder__num_decoded_frames(
12398 const wuffs_base__image_decoder* self) {
12399 if (!self) {
12400 return 0;
12401 }
12402 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12403 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12404 return 0;
12405 }
12406
12407 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12408 int i;
12409 for (i = 0; i < 63; i++) {
12410 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12411 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12412 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12413 return (*func_ptrs->num_decoded_frames)(self);
12414 } else if (v->vtable_name == NULL) {
12415 break;
12416 }
12417 v++;
12418 }
12419
12420 return 0;
12421}
12422
12423WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12424wuffs_base__image_decoder__restart_frame(
12425 wuffs_base__image_decoder* self,
12426 uint64_t a_index,
12427 uint64_t a_io_position) {
12428 if (!self) {
12429 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12430 }
12431 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12432 return wuffs_base__make_status(
12433 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12434 ? wuffs_base__error__disabled_by_previous_error
12435 : wuffs_base__error__initialize_not_called);
12436 }
12437
12438 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12439 int i;
12440 for (i = 0; i < 63; i++) {
12441 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12442 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12443 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12444 return (*func_ptrs->restart_frame)(self, a_index, a_io_position);
12445 } else if (v->vtable_name == NULL) {
12446 break;
12447 }
12448 v++;
12449 }
12450
12451 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12452}
12453
12454WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
12455wuffs_base__image_decoder__set_quirk_enabled(
12456 wuffs_base__image_decoder* self,
12457 uint32_t a_quirk,
12458 bool a_enabled) {
12459 if (!self) {
12460 return wuffs_base__make_empty_struct();
12461 }
12462 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12463 return wuffs_base__make_empty_struct();
12464 }
12465
12466 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12467 int i;
12468 for (i = 0; i < 63; i++) {
12469 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12470 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12471 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12472 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
12473 } else if (v->vtable_name == NULL) {
12474 break;
12475 }
12476 v++;
12477 }
12478
12479 return wuffs_base__make_empty_struct();
12480}
12481
12482WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
12483wuffs_base__image_decoder__set_report_metadata(
12484 wuffs_base__image_decoder* self,
12485 uint32_t a_fourcc,
12486 bool a_report) {
12487 if (!self) {
12488 return wuffs_base__make_empty_struct();
12489 }
12490 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12491 return wuffs_base__make_empty_struct();
12492 }
12493
12494 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12495 int i;
12496 for (i = 0; i < 63; i++) {
12497 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12498 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12499 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12500 return (*func_ptrs->set_report_metadata)(self, a_fourcc, a_report);
12501 } else if (v->vtable_name == NULL) {
12502 break;
12503 }
12504 v++;
12505 }
12506
12507 return wuffs_base__make_empty_struct();
12508}
12509
12510WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12511wuffs_base__image_decoder__tell_me_more(
12512 wuffs_base__image_decoder* self,
12513 wuffs_base__io_buffer* a_dst,
12514 wuffs_base__more_information* a_minfo,
12515 wuffs_base__io_buffer* a_src) {
12516 if (!self) {
12517 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12518 }
12519 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12520 return wuffs_base__make_status(
12521 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12522 ? wuffs_base__error__disabled_by_previous_error
12523 : wuffs_base__error__initialize_not_called);
12524 }
12525
12526 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12527 int i;
12528 for (i = 0; i < 63; i++) {
12529 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12530 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12531 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12532 return (*func_ptrs->tell_me_more)(self, a_dst, a_minfo, a_src);
12533 } else if (v->vtable_name == NULL) {
12534 break;
12535 }
12536 v++;
12537 }
12538
12539 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12540}
12541
12542WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
12543wuffs_base__image_decoder__workbuf_len(
12544 const wuffs_base__image_decoder* self) {
12545 if (!self) {
12546 return wuffs_base__utility__empty_range_ii_u64();
12547 }
12548 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12549 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12550 return wuffs_base__utility__empty_range_ii_u64();
12551 }
12552
12553 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12554 int i;
12555 for (i = 0; i < 63; i++) {
12556 if (v->vtable_name == wuffs_base__image_decoder__vtable_name) {
12557 const wuffs_base__image_decoder__func_ptrs* func_ptrs =
12558 (const wuffs_base__image_decoder__func_ptrs*)(v->function_pointers);
12559 return (*func_ptrs->workbuf_len)(self);
12560 } else if (v->vtable_name == NULL) {
12561 break;
12562 }
12563 v++;
12564 }
12565
12566 return wuffs_base__utility__empty_range_ii_u64();
12567}
12568
12569// --------
12570
12571WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
12572wuffs_base__io_transformer__set_quirk_enabled(
12573 wuffs_base__io_transformer* self,
12574 uint32_t a_quirk,
12575 bool a_enabled) {
12576 if (!self) {
12577 return wuffs_base__make_empty_struct();
12578 }
12579 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12580 return wuffs_base__make_empty_struct();
12581 }
12582
12583 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12584 int i;
12585 for (i = 0; i < 63; i++) {
12586 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
12587 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
12588 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
12589 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
12590 } else if (v->vtable_name == NULL) {
12591 break;
12592 }
12593 v++;
12594 }
12595
12596 return wuffs_base__make_empty_struct();
12597}
12598
12599WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12600wuffs_base__io_transformer__transform_io(
12601 wuffs_base__io_transformer* self,
12602 wuffs_base__io_buffer* a_dst,
12603 wuffs_base__io_buffer* a_src,
12604 wuffs_base__slice_u8 a_workbuf) {
12605 if (!self) {
12606 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12607 }
12608 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12609 return wuffs_base__make_status(
12610 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12611 ? wuffs_base__error__disabled_by_previous_error
12612 : wuffs_base__error__initialize_not_called);
12613 }
12614
12615 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12616 int i;
12617 for (i = 0; i < 63; i++) {
12618 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
12619 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
12620 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
12621 return (*func_ptrs->transform_io)(self, a_dst, a_src, a_workbuf);
12622 } else if (v->vtable_name == NULL) {
12623 break;
12624 }
12625 v++;
12626 }
12627
12628 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12629}
12630
12631WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
12632wuffs_base__io_transformer__workbuf_len(
12633 const wuffs_base__io_transformer* self) {
12634 if (!self) {
12635 return wuffs_base__utility__empty_range_ii_u64();
12636 }
12637 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12638 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12639 return wuffs_base__utility__empty_range_ii_u64();
12640 }
12641
12642 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12643 int i;
12644 for (i = 0; i < 63; i++) {
12645 if (v->vtable_name == wuffs_base__io_transformer__vtable_name) {
12646 const wuffs_base__io_transformer__func_ptrs* func_ptrs =
12647 (const wuffs_base__io_transformer__func_ptrs*)(v->function_pointers);
12648 return (*func_ptrs->workbuf_len)(self);
12649 } else if (v->vtable_name == NULL) {
12650 break;
12651 }
12652 v++;
12653 }
12654
12655 return wuffs_base__utility__empty_range_ii_u64();
12656}
12657
12658// --------
12659
12660WUFFS_BASE__MAYBE_STATIC wuffs_base__status
12661wuffs_base__token_decoder__decode_tokens(
12662 wuffs_base__token_decoder* self,
12663 wuffs_base__token_buffer* a_dst,
12664 wuffs_base__io_buffer* a_src,
12665 wuffs_base__slice_u8 a_workbuf) {
12666 if (!self) {
12667 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
12668 }
12669 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12670 return wuffs_base__make_status(
12671 (self->private_impl.magic == WUFFS_BASE__DISABLED)
12672 ? wuffs_base__error__disabled_by_previous_error
12673 : wuffs_base__error__initialize_not_called);
12674 }
12675
12676 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12677 int i;
12678 for (i = 0; i < 63; i++) {
12679 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
12680 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
12681 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
12682 return (*func_ptrs->decode_tokens)(self, a_dst, a_src, a_workbuf);
12683 } else if (v->vtable_name == NULL) {
12684 break;
12685 }
12686 v++;
12687 }
12688
12689 return wuffs_base__make_status(wuffs_base__error__bad_vtable);
12690}
12691
12692WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
12693wuffs_base__token_decoder__set_quirk_enabled(
12694 wuffs_base__token_decoder* self,
12695 uint32_t a_quirk,
12696 bool a_enabled) {
12697 if (!self) {
12698 return wuffs_base__make_empty_struct();
12699 }
12700 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
12701 return wuffs_base__make_empty_struct();
12702 }
12703
12704 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12705 int i;
12706 for (i = 0; i < 63; i++) {
12707 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
12708 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
12709 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
12710 return (*func_ptrs->set_quirk_enabled)(self, a_quirk, a_enabled);
12711 } else if (v->vtable_name == NULL) {
12712 break;
12713 }
12714 v++;
12715 }
12716
12717 return wuffs_base__make_empty_struct();
12718}
12719
12720WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
12721wuffs_base__token_decoder__workbuf_len(
12722 const wuffs_base__token_decoder* self) {
12723 if (!self) {
12724 return wuffs_base__utility__empty_range_ii_u64();
12725 }
12726 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
12727 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
12728 return wuffs_base__utility__empty_range_ii_u64();
12729 }
12730
12731 const wuffs_base__vtable* v = &self->private_impl.first_vtable;
12732 int i;
12733 for (i = 0; i < 63; i++) {
12734 if (v->vtable_name == wuffs_base__token_decoder__vtable_name) {
12735 const wuffs_base__token_decoder__func_ptrs* func_ptrs =
12736 (const wuffs_base__token_decoder__func_ptrs*)(v->function_pointers);
12737 return (*func_ptrs->workbuf_len)(self);
12738 } else if (v->vtable_name == NULL) {
12739 break;
12740 }
12741 v++;
12742 }
12743
12744 return wuffs_base__utility__empty_range_ii_u64();
12745}
12746
12747#endif // !defined(WUFFS_CONFIG__MODULES) ||
12748 // defined(WUFFS_CONFIG__MODULE__BASE) ||
12749 // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)
12750
12751#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
12752 defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV)
12753
12754// ---------------- IEEE 754 Floating Point
12755
12756// The etc__hpd_left_shift and etc__powers_of_5 tables were printed by
12757// script/print-hpd-left-shift.go. That script has an optional -comments flag,
12758// whose output is not copied here, which prints further detail.
12759//
12760// These tables are used in
12761// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits.
12762
12763// wuffs_base__private_implementation__hpd_left_shift[i] encodes the number of
12764// new digits created after multiplying a positive integer by (1 << i): the
12765// additional length in the decimal representation. For example, shifting "234"
12766// by 3 (equivalent to multiplying by 8) will produce "1872". Going from a
12767// 3-length string to a 4-length string means that 1 new digit was added (and
12768// existing digits may have changed).
12769//
12770// Shifting by i can add either N or N-1 new digits, depending on whether the
12771// original positive integer compares >= or < to the i'th power of 5 (as 10
12772// equals 2 * 5). Comparison is lexicographic, not numerical.
12773//
12774// For example, shifting by 4 (i.e. multiplying by 16) can add 1 or 2 new
12775// digits, depending on a lexicographic comparison to (5 ** 4), i.e. "625":
12776// - ("1" << 4) is "16", which adds 1 new digit.
12777// - ("5678" << 4) is "90848", which adds 1 new digit.
12778// - ("624" << 4) is "9984", which adds 1 new digit.
12779// - ("62498" << 4) is "999968", which adds 1 new digit.
12780// - ("625" << 4) is "10000", which adds 2 new digits.
12781// - ("625001" << 4) is "10000016", which adds 2 new digits.
12782// - ("7008" << 4) is "112128", which adds 2 new digits.
12783// - ("99" << 4) is "1584", which adds 2 new digits.
12784//
12785// Thus, when i is 4, N is 2 and (5 ** i) is "625". This etc__hpd_left_shift
12786// array encodes this as:
12787// - etc__hpd_left_shift[4] is 0x1006 = (2 << 11) | 0x0006.
12788// - etc__hpd_left_shift[5] is 0x1009 = (? << 11) | 0x0009.
12789// where the ? isn't relevant for i == 4.
12790//
12791// The high 5 bits of etc__hpd_left_shift[i] is N, the higher of the two
12792// possible number of new digits. The low 11 bits are an offset into the
12793// etc__powers_of_5 array (of length 0x051C, so offsets fit in 11 bits). When i
12794// is 4, its offset and the next one is 6 and 9, and etc__powers_of_5[6 .. 9]
12795// is the string "\x06\x02\x05", so the relevant power of 5 is "625".
12796//
12797// Thanks to Ken Thompson for the original idea.
12798static const uint16_t wuffs_base__private_implementation__hpd_left_shift[65] = {
12799 0x0000, 0x0800, 0x0801, 0x0803, 0x1006, 0x1009, 0x100D, 0x1812, 0x1817,
12800 0x181D, 0x2024, 0x202B, 0x2033, 0x203C, 0x2846, 0x2850, 0x285B, 0x3067,
12801 0x3073, 0x3080, 0x388E, 0x389C, 0x38AB, 0x38BB, 0x40CC, 0x40DD, 0x40EF,
12802 0x4902, 0x4915, 0x4929, 0x513E, 0x5153, 0x5169, 0x5180, 0x5998, 0x59B0,
12803 0x59C9, 0x61E3, 0x61FD, 0x6218, 0x6A34, 0x6A50, 0x6A6D, 0x6A8B, 0x72AA,
12804 0x72C9, 0x72E9, 0x7B0A, 0x7B2B, 0x7B4D, 0x8370, 0x8393, 0x83B7, 0x83DC,
12805 0x8C02, 0x8C28, 0x8C4F, 0x9477, 0x949F, 0x94C8, 0x9CF2, 0x051C, 0x051C,
12806 0x051C, 0x051C,
12807};
12808
12809// wuffs_base__private_implementation__powers_of_5 contains the powers of 5,
12810// concatenated together: "5", "25", "125", "625", "3125", etc.
12811static const uint8_t wuffs_base__private_implementation__powers_of_5[0x051C] = {
12812 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,
12813 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,
12814 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,
12815 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,
12816 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,
12817 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,
12818 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,
12819 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,
12820 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,
12821 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,
12822 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,
12823 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,
12824 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,
12825 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,
12826 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,
12827 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,
12828 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,
12829 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,
12830 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,
12831 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,
12832 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,
12833 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,
12834 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,
12835 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,
12836 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,
12837 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,
12838 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,
12839 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,
12840 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,
12841 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,
12842 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,
12843 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,
12844 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,
12845 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,
12846 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,
12847 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,
12848 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,
12849 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,
12850 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,
12851 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,
12852 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,
12853 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,
12854 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,
12855 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,
12856 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,
12857 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,
12858 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,
12859 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,
12860 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,
12861 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,
12862 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,
12863 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,
12864 6, 9, 1, 4, 0, 6, 2, 5,
12865};
12866
12867// --------
12868
12869// wuffs_base__private_implementation__powers_of_10 contains truncated
12870// approximations to the powers of 10, ranging from 1e-307 to 1e+288 inclusive,
12871// as 596 pairs of uint64_t values (a 128-bit mantissa).
12872//
12873// There's also an implicit third column (implied by a linear formula involving
12874// the base-10 exponent) that is the base-2 exponent, biased by a magic
12875// constant. That constant (1214 or 0x04BE) equals 1023 + 191. 1023 is the bias
12876// for IEEE 754 double-precision floating point. 191 is ((3 * 64) - 1) and
12877// wuffs_base__private_implementation__parse_number_f64_eisel_lemire works with
12878// multiples-of-64-bit mantissas.
12879//
12880// For example, the third row holds the approximation to 1e-305:
12881// 0xE0B62E29_29ABA83C_331ACDAB_FE94DE87 * (2 ** (0x0049 - 0x04BE))
12882//
12883// Similarly, 1e+4 is approximated by:
12884// 0x9C400000_00000000_00000000_00000000 * (2 ** (0x044C - 0x04BE))
12885//
12886// Similarly, 1e+68 is approximated by:
12887// 0xED63A231_D4C4FB27_4CA7AAA8_63EE4BDD * (2 ** (0x0520 - 0x04BE))
12888//
12889// This table was generated by by script/print-mpb-powers-of-10.go
12890static const uint64_t wuffs_base__private_implementation__powers_of_10[596][2] =
12891 {
12892 {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307
12893 {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306
12894 {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305
12895 {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304
12896 {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303
12897 {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302
12898 {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301
12899 {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300
12900 {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299
12901 {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298
12902 {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297
12903 {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296
12904 {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295
12905 {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294
12906 {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293
12907 {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292
12908 {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291
12909 {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290
12910 {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289
12911 {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288
12912 {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287
12913 {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286
12914 {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285
12915 {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284
12916 {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283
12917 {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282
12918 {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281
12919 {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280
12920 {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279
12921 {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278
12922 {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277
12923 {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276
12924 {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275
12925 {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274
12926 {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273
12927 {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272
12928 {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271
12929 {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270
12930 {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269
12931 {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268
12932 {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267
12933 {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266
12934 {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265
12935 {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264
12936 {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263
12937 {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262
12938 {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261
12939 {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260
12940 {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259
12941 {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258
12942 {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257
12943 {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256
12944 {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255
12945 {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254
12946 {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253
12947 {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252
12948 {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251
12949 {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250
12950 {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249
12951 {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248
12952 {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247
12953 {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246
12954 {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245
12955 {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244
12956 {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243
12957 {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242
12958 {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241
12959 {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240
12960 {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239
12961 {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238
12962 {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237
12963 {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236
12964 {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235
12965 {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234
12966 {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233
12967 {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232
12968 {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231
12969 {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230
12970 {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229
12971 {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228
12972 {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227
12973 {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226
12974 {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225
12975 {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224
12976 {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223
12977 {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222
12978 {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221
12979 {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220
12980 {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219
12981 {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218
12982 {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217
12983 {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216
12984 {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215
12985 {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214
12986 {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213
12987 {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212
12988 {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211
12989 {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210
12990 {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209
12991 {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208
12992 {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207
12993 {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206
12994 {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205
12995 {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204
12996 {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203
12997 {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202
12998 {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201
12999 {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200
13000 {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199
13001 {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198
13002 {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197
13003 {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196
13004 {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195
13005 {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194
13006 {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193
13007 {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192
13008 {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191
13009 {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190
13010 {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189
13011 {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188
13012 {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187
13013 {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186
13014 {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185
13015 {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184
13016 {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183
13017 {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182
13018 {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181
13019 {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180
13020 {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179
13021 {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178
13022 {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177
13023 {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176
13024 {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175
13025 {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174
13026 {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173
13027 {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172
13028 {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171
13029 {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170
13030 {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169
13031 {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168
13032 {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167
13033 {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166
13034 {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165
13035 {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164
13036 {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163
13037 {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162
13038 {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161
13039 {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160
13040 {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159
13041 {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158
13042 {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157
13043 {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156
13044 {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155
13045 {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154
13046 {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153
13047 {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152
13048 {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151
13049 {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150
13050 {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149
13051 {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148
13052 {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147
13053 {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146
13054 {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145
13055 {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144
13056 {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143
13057 {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142
13058 {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141
13059 {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140
13060 {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139
13061 {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138
13062 {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137
13063 {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136
13064 {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135
13065 {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134
13066 {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133
13067 {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132
13068 {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131
13069 {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130
13070 {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129
13071 {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128
13072 {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127
13073 {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126
13074 {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125
13075 {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124
13076 {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123
13077 {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122
13078 {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121
13079 {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120
13080 {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119
13081 {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118
13082 {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117
13083 {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116
13084 {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115
13085 {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114
13086 {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113
13087 {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112
13088 {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111
13089 {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110
13090 {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109
13091 {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108
13092 {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107
13093 {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106
13094 {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105
13095 {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104
13096 {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103
13097 {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102
13098 {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101
13099 {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100
13100 {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99
13101 {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98
13102 {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97
13103 {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96
13104 {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95
13105 {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94
13106 {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93
13107 {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92
13108 {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91
13109 {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90
13110 {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89
13111 {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88
13112 {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87
13113 {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86
13114 {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85
13115 {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84
13116 {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83
13117 {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82
13118 {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81
13119 {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80
13120 {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79
13121 {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78
13122 {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77
13123 {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76
13124 {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75
13125 {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74
13126 {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73
13127 {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72
13128 {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71
13129 {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70
13130 {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69
13131 {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68
13132 {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67
13133 {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66
13134 {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65
13135 {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64
13136 {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63
13137 {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62
13138 {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61
13139 {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60
13140 {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59
13141 {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58
13142 {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57
13143 {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56
13144 {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55
13145 {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54
13146 {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53
13147 {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52
13148 {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51
13149 {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50
13150 {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49
13151 {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48
13152 {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47
13153 {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46
13154 {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45
13155 {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44
13156 {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43
13157 {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42
13158 {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41
13159 {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40
13160 {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39
13161 {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38
13162 {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37
13163 {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36
13164 {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35
13165 {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34
13166 {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33
13167 {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32
13168 {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31
13169 {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30
13170 {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29
13171 {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28
13172 {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27
13173 {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26
13174 {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25
13175 {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24
13176 {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23
13177 {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22
13178 {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21
13179 {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20
13180 {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19
13181 {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18
13182 {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17
13183 {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16
13184 {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15
13185 {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14
13186 {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13
13187 {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12
13188 {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11
13189 {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10
13190 {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9
13191 {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8
13192 {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7
13193 {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6
13194 {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5
13195 {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4
13196 {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3
13197 {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2
13198 {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1
13199 {0x0000000000000000, 0x8000000000000000}, // 1e0
13200 {0x0000000000000000, 0xA000000000000000}, // 1e1
13201 {0x0000000000000000, 0xC800000000000000}, // 1e2
13202 {0x0000000000000000, 0xFA00000000000000}, // 1e3
13203 {0x0000000000000000, 0x9C40000000000000}, // 1e4
13204 {0x0000000000000000, 0xC350000000000000}, // 1e5
13205 {0x0000000000000000, 0xF424000000000000}, // 1e6
13206 {0x0000000000000000, 0x9896800000000000}, // 1e7
13207 {0x0000000000000000, 0xBEBC200000000000}, // 1e8
13208 {0x0000000000000000, 0xEE6B280000000000}, // 1e9
13209 {0x0000000000000000, 0x9502F90000000000}, // 1e10
13210 {0x0000000000000000, 0xBA43B74000000000}, // 1e11
13211 {0x0000000000000000, 0xE8D4A51000000000}, // 1e12
13212 {0x0000000000000000, 0x9184E72A00000000}, // 1e13
13213 {0x0000000000000000, 0xB5E620F480000000}, // 1e14
13214 {0x0000000000000000, 0xE35FA931A0000000}, // 1e15
13215 {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16
13216 {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17
13217 {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18
13218 {0x0000000000000000, 0x8AC7230489E80000}, // 1e19
13219 {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20
13220 {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21
13221 {0x0000000000000000, 0x878678326EAC9000}, // 1e22
13222 {0x0000000000000000, 0xA968163F0A57B400}, // 1e23
13223 {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24
13224 {0x0000000000000000, 0x84595161401484A0}, // 1e25
13225 {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26
13226 {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27
13227 {0x4000000000000000, 0x813F3978F8940984}, // 1e28
13228 {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29
13229 {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30
13230 {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31
13231 {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32
13232 {0x6C28000000000000, 0xC5371912364CE305}, // 1e33
13233 {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34
13234 {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35
13235 {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36
13236 {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37
13237 {0x1314448000000000, 0x96769950B50D88F4}, // 1e38
13238 {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39
13239 {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40
13240 {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41
13241 {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42
13242 {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43
13243 {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44
13244 {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45
13245 {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46
13246 {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47
13247 {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48
13248 {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49
13249 {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50
13250 {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51
13251 {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52
13252 {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53
13253 {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54
13254 {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55
13255 {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56
13256 {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57
13257 {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58
13258 {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59
13259 {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60
13260 {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61
13261 {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62
13262 {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63
13263 {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64
13264 {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65
13265 {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66
13266 {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67
13267 {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68
13268 {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69
13269 {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70
13270 {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71
13271 {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72
13272 {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73
13273 {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74
13274 {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75
13275 {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76
13276 {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77
13277 {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78
13278 {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79
13279 {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80
13280 {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81
13281 {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82
13282 {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83
13283 {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84
13284 {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85
13285 {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86
13286 {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87
13287 {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88
13288 {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89
13289 {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90
13290 {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91
13291 {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92
13292 {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93
13293 {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94
13294 {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95
13295 {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96
13296 {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97
13297 {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98
13298 {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99
13299 {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100
13300 {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101
13301 {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102
13302 {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103
13303 {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104
13304 {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105
13305 {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106
13306 {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107
13307 {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108
13308 {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109
13309 {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110
13310 {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111
13311 {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112
13312 {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113
13313 {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114
13314 {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115
13315 {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116
13316 {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117
13317 {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118
13318 {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119
13319 {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120
13320 {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121
13321 {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122
13322 {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123
13323 {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124
13324 {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125
13325 {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126
13326 {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127
13327 {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128
13328 {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129
13329 {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130
13330 {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131
13331 {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132
13332 {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133
13333 {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134
13334 {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135
13335 {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136
13336 {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137
13337 {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138
13338 {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139
13339 {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140
13340 {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141
13341 {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142
13342 {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143
13343 {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144
13344 {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145
13345 {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146
13346 {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147
13347 {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148
13348 {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149
13349 {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150
13350 {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151
13351 {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152
13352 {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153
13353 {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154
13354 {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155
13355 {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156
13356 {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157
13357 {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158
13358 {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159
13359 {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160
13360 {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161
13361 {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162
13362 {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163
13363 {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164
13364 {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165
13365 {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166
13366 {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167
13367 {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168
13368 {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169
13369 {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170
13370 {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171
13371 {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172
13372 {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173
13373 {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174
13374 {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175
13375 {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176
13376 {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177
13377 {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178
13378 {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179
13379 {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180
13380 {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181
13381 {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182
13382 {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183
13383 {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184
13384 {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185
13385 {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186
13386 {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187
13387 {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188
13388 {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189
13389 {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190
13390 {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191
13391 {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192
13392 {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193
13393 {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194
13394 {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195
13395 {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196
13396 {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197
13397 {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198
13398 {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199
13399 {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200
13400 {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201
13401 {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202
13402 {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203
13403 {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204
13404 {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205
13405 {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206
13406 {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207
13407 {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208
13408 {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209
13409 {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210
13410 {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211
13411 {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212
13412 {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213
13413 {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214
13414 {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215
13415 {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216
13416 {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217
13417 {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218
13418 {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219
13419 {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220
13420 {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221
13421 {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222
13422 {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223
13423 {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224
13424 {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225
13425 {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226
13426 {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227
13427 {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228
13428 {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229
13429 {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230
13430 {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231
13431 {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232
13432 {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233
13433 {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234
13434 {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235
13435 {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236
13436 {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237
13437 {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238
13438 {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239
13439 {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240
13440 {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241
13441 {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242
13442 {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243
13443 {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244
13444 {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245
13445 {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246
13446 {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247
13447 {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248
13448 {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249
13449 {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250
13450 {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251
13451 {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252
13452 {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253
13453 {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254
13454 {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255
13455 {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256
13456 {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257
13457 {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258
13458 {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259
13459 {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260
13460 {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261
13461 {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262
13462 {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263
13463 {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264
13464 {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265
13465 {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266
13466 {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267
13467 {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268
13468 {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269
13469 {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270
13470 {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271
13471 {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272
13472 {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273
13473 {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274
13474 {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275
13475 {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276
13476 {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277
13477 {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278
13478 {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279
13479 {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280
13480 {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281
13481 {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282
13482 {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283
13483 {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284
13484 {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285
13485 {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286
13486 {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287
13487 {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288
13488};
13489
13490// wuffs_base__private_implementation__f64_powers_of_10 holds powers of 10 that
13491// can be exactly represented by a float64 (what C calls a double).
13492static const double wuffs_base__private_implementation__f64_powers_of_10[23] = {
13493 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11,
13494 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22,
13495};
13496
13497// ---------------- IEEE 754 Floating Point
13498
13499WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u16 //
13500wuffs_base__ieee_754_bit_representation__from_f64_to_u16_truncate(double f) {
13501 uint64_t u = 0;
13502 if (sizeof(uint64_t) == sizeof(double)) {
13503 memcpy(&u, &f, sizeof(uint64_t));
13504 }
13505 uint16_t neg = ((uint16_t)((u >> 63) << 15));
13506 u &= 0x7FFFFFFFFFFFFFFF;
13507 uint64_t exp = u >> 52;
13508 uint64_t man = u & 0x000FFFFFFFFFFFFF;
13509
13510 if (exp == 0x7FF) {
13511 if (man == 0) { // Infinity.
13512 wuffs_base__lossy_value_u16 ret;
13513 ret.value = neg | 0x7C00;
13514 ret.lossy = false;
13515 return ret;
13516 }
13517 // NaN. Shift the 52 mantissa bits to 10 mantissa bits, keeping the most
13518 // significant mantissa bit (quiet vs signaling NaNs). Also set the low 9
13519 // bits of ret.value so that the 10-bit mantissa is non-zero.
13520 wuffs_base__lossy_value_u16 ret;
13521 ret.value = neg | 0x7DFF | ((uint16_t)(man >> 42));
13522 ret.lossy = false;
13523 return ret;
13524
13525 } else if (exp > 0x40E) { // Truncate to the largest finite f16.
13526 wuffs_base__lossy_value_u16 ret;
13527 ret.value = neg | 0x7BFF;
13528 ret.lossy = true;
13529 return ret;
13530
13531 } else if (exp <= 0x3E6) { // Truncate to zero.
13532 wuffs_base__lossy_value_u16 ret;
13533 ret.value = neg;
13534 ret.lossy = (u != 0);
13535 return ret;
13536
13537 } else if (exp <= 0x3F0) { // Normal f64, subnormal f16.
13538 // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
13539 // 10-bit mantissa and then adjust for the exponent.
13540 man |= 0x0010000000000000;
13541 uint32_t shift = ((uint32_t)(1051 - exp)); // 1051 = 0x3F0 + 53 - 10.
13542 uint64_t shifted_man = man >> shift;
13543 wuffs_base__lossy_value_u16 ret;
13544 ret.value = neg | ((uint16_t)shifted_man);
13545 ret.lossy = (shifted_man << shift) != man;
13546 return ret;
13547 }
13548
13549 // Normal f64, normal f16.
13550
13551 // Re-bias from 1023 to 15 and shift above f16's 10 mantissa bits.
13552 exp = (exp - 1008) << 10; // 1008 = 1023 - 15 = 0x3FF - 0xF.
13553
13554 // Convert from a 52-bit mantissa (excluding the implicit bit) to a 10-bit
13555 // mantissa (again excluding the implicit bit). We lose some information if
13556 // any of the bottom 42 bits are non-zero.
13557 wuffs_base__lossy_value_u16 ret;
13558 ret.value = neg | ((uint16_t)exp) | ((uint16_t)(man >> 42));
13559 ret.lossy = (man << 22) != 0;
13560 return ret;
13561}
13562
13563WUFFS_BASE__MAYBE_STATIC wuffs_base__lossy_value_u32 //
13564wuffs_base__ieee_754_bit_representation__from_f64_to_u32_truncate(double f) {
13565 uint64_t u = 0;
13566 if (sizeof(uint64_t) == sizeof(double)) {
13567 memcpy(&u, &f, sizeof(uint64_t));
13568 }
13569 uint32_t neg = ((uint32_t)(u >> 63)) << 31;
13570 u &= 0x7FFFFFFFFFFFFFFF;
13571 uint64_t exp = u >> 52;
13572 uint64_t man = u & 0x000FFFFFFFFFFFFF;
13573
13574 if (exp == 0x7FF) {
13575 if (man == 0) { // Infinity.
13576 wuffs_base__lossy_value_u32 ret;
13577 ret.value = neg | 0x7F800000;
13578 ret.lossy = false;
13579 return ret;
13580 }
13581 // NaN. Shift the 52 mantissa bits to 23 mantissa bits, keeping the most
13582 // significant mantissa bit (quiet vs signaling NaNs). Also set the low 22
13583 // bits of ret.value so that the 23-bit mantissa is non-zero.
13584 wuffs_base__lossy_value_u32 ret;
13585 ret.value = neg | 0x7FBFFFFF | ((uint32_t)(man >> 29));
13586 ret.lossy = false;
13587 return ret;
13588
13589 } else if (exp > 0x47E) { // Truncate to the largest finite f32.
13590 wuffs_base__lossy_value_u32 ret;
13591 ret.value = neg | 0x7F7FFFFF;
13592 ret.lossy = true;
13593 return ret;
13594
13595 } else if (exp <= 0x369) { // Truncate to zero.
13596 wuffs_base__lossy_value_u32 ret;
13597 ret.value = neg;
13598 ret.lossy = (u != 0);
13599 return ret;
13600
13601 } else if (exp <= 0x380) { // Normal f64, subnormal f32.
13602 // Convert from a 53-bit mantissa (after realizing the implicit bit) to a
13603 // 23-bit mantissa and then adjust for the exponent.
13604 man |= 0x0010000000000000;
13605 uint32_t shift = ((uint32_t)(926 - exp)); // 926 = 0x380 + 53 - 23.
13606 uint64_t shifted_man = man >> shift;
13607 wuffs_base__lossy_value_u32 ret;
13608 ret.value = neg | ((uint32_t)shifted_man);
13609 ret.lossy = (shifted_man << shift) != man;
13610 return ret;
13611 }
13612
13613 // Normal f64, normal f32.
13614
13615 // Re-bias from 1023 to 127 and shift above f32's 23 mantissa bits.
13616 exp = (exp - 896) << 23; // 896 = 1023 - 127 = 0x3FF - 0x7F.
13617
13618 // Convert from a 52-bit mantissa (excluding the implicit bit) to a 23-bit
13619 // mantissa (again excluding the implicit bit). We lose some information if
13620 // any of the bottom 29 bits are non-zero.
13621 wuffs_base__lossy_value_u32 ret;
13622 ret.value = neg | ((uint32_t)exp) | ((uint32_t)(man >> 29));
13623 ret.lossy = (man << 35) != 0;
13624 return ret;
13625}
13626
13627// --------
13628
13629#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE 2047
13630#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION 800
13631
13632// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL is the largest N
13633// such that ((10 << N) < (1 << 64)).
13634#define WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL 60
13635
13636// wuffs_base__private_implementation__high_prec_dec (abbreviated as HPD) is a
13637// fixed precision floating point decimal number, augmented with ±infinity
13638// values, but it cannot represent NaN (Not a Number).
13639//
13640// "High precision" means that the mantissa holds 800 decimal digits. 800 is
13641// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION.
13642//
13643// An HPD isn't for general purpose arithmetic, only for conversions to and
13644// from IEEE 754 double-precision floating point, where the largest and
13645// smallest positive, finite values are approximately 1.8e+308 and 4.9e-324.
13646// HPD exponents above +2047 mean infinity, below -2047 mean zero. The ±2047
13647// bounds are further away from zero than ±(324 + 800), where 800 and 2047 is
13648// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION and
13649// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
13650//
13651// digits[.. num_digits] are the number's digits in big-endian order. The
13652// uint8_t values are in the range [0 ..= 9], not ['0' ..= '9'], where e.g. '7'
13653// is the ASCII value 0x37.
13654//
13655// decimal_point is the index (within digits) of the decimal point. It may be
13656// negative or be larger than num_digits, in which case the explicit digits are
13657// padded with implicit zeroes.
13658//
13659// For example, if num_digits is 3 and digits is "\x07\x08\x09":
Nigel Taobf9dab32021-11-18 19:19:55 +110013660// - A decimal_point of -2 means ".00789"
13661// - A decimal_point of -1 means ".0789"
13662// - A decimal_point of +0 means ".789"
13663// - A decimal_point of +1 means "7.89"
13664// - A decimal_point of +2 means "78.9"
13665// - A decimal_point of +3 means "789."
13666// - A decimal_point of +4 means "7890."
13667// - A decimal_point of +5 means "78900."
Nigel Taoe360a532021-04-05 22:47:03 +100013668//
13669// As above, a decimal_point higher than +2047 means that the overall value is
13670// infinity, lower than -2047 means zero.
13671//
13672// negative is a sign bit. An HPD can distinguish positive and negative zero.
13673//
13674// truncated is whether there are more than
13675// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION digits, and at
13676// least one of those extra digits are non-zero. The existence of long-tail
13677// digits can affect rounding.
13678//
13679// The "all fields are zero" value is valid, and represents the number +0.
13680typedef struct wuffs_base__private_implementation__high_prec_dec__struct {
13681 uint32_t num_digits;
13682 int32_t decimal_point;
13683 bool negative;
13684 bool truncated;
13685 uint8_t digits[WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION];
13686} wuffs_base__private_implementation__high_prec_dec;
13687
13688// wuffs_base__private_implementation__high_prec_dec__trim trims trailing
13689// zeroes from the h->digits[.. h->num_digits] slice. They have no benefit,
13690// since we explicitly track h->decimal_point.
13691//
13692// Preconditions:
13693// - h is non-NULL.
13694static inline void //
13695wuffs_base__private_implementation__high_prec_dec__trim(
13696 wuffs_base__private_implementation__high_prec_dec* h) {
13697 while ((h->num_digits > 0) && (h->digits[h->num_digits - 1] == 0)) {
13698 h->num_digits--;
13699 }
13700}
13701
13702// wuffs_base__private_implementation__high_prec_dec__assign sets h to
13703// represent the number x.
13704//
13705// Preconditions:
13706// - h is non-NULL.
13707static void //
13708wuffs_base__private_implementation__high_prec_dec__assign(
13709 wuffs_base__private_implementation__high_prec_dec* h,
13710 uint64_t x,
13711 bool negative) {
13712 uint32_t n = 0;
13713
13714 // Set h->digits.
13715 if (x > 0) {
13716 // Calculate the digits, working right-to-left. After we determine n (how
13717 // many digits there are), copy from buf to h->digits.
13718 //
13719 // UINT64_MAX, 18446744073709551615, is 20 digits long. It can be faster to
13720 // copy a constant number of bytes than a variable number (20 instead of
13721 // n). Make buf large enough (and start writing to it from the middle) so
13722 // that can we always copy 20 bytes: the slice buf[(20-n) .. (40-n)].
13723 uint8_t buf[40] = {0};
13724 uint8_t* ptr = &buf[20];
13725 do {
13726 uint64_t remaining = x / 10;
13727 x -= remaining * 10;
13728 ptr--;
13729 *ptr = (uint8_t)x;
13730 n++;
13731 x = remaining;
13732 } while (x > 0);
13733 memcpy(h->digits, ptr, 20);
13734 }
13735
13736 // Set h's other fields.
13737 h->num_digits = n;
13738 h->decimal_point = (int32_t)n;
13739 h->negative = negative;
13740 h->truncated = false;
13741 wuffs_base__private_implementation__high_prec_dec__trim(h);
13742}
13743
13744static wuffs_base__status //
13745wuffs_base__private_implementation__high_prec_dec__parse(
13746 wuffs_base__private_implementation__high_prec_dec* h,
13747 wuffs_base__slice_u8 s,
13748 uint32_t options) {
13749 if (!h) {
13750 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
13751 }
13752 h->num_digits = 0;
13753 h->decimal_point = 0;
13754 h->negative = false;
13755 h->truncated = false;
13756
13757 uint8_t* p = s.ptr;
13758 uint8_t* q = s.ptr + s.len;
13759
13760 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
13761 for (;; p++) {
13762 if (p >= q) {
13763 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13764 } else if (*p != '_') {
13765 break;
13766 }
13767 }
13768 }
13769
13770 // Parse sign.
13771 do {
13772 if (*p == '+') {
13773 p++;
13774 } else if (*p == '-') {
13775 h->negative = true;
13776 p++;
13777 } else {
13778 break;
13779 }
13780 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
13781 for (;; p++) {
13782 if (p >= q) {
13783 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13784 } else if (*p != '_') {
13785 break;
13786 }
13787 }
13788 }
13789 } while (0);
13790
13791 // Parse digits, up to (and including) a '.', 'E' or 'e'. Examples for each
13792 // limb in this if-else chain:
13793 // - "0.789"
13794 // - "1002.789"
13795 // - ".789"
13796 // - Other (invalid input).
13797 uint32_t nd = 0;
13798 int32_t dp = 0;
13799 bool no_digits_before_separator = false;
13800 if (('0' == *p) &&
13801 !(options &
13802 WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES)) {
13803 p++;
13804 for (;; p++) {
13805 if (p >= q) {
13806 goto after_all;
13807 } else if (*p ==
13808 ((options &
13809 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13810 ? ','
13811 : '.')) {
13812 p++;
13813 goto after_sep;
13814 } else if ((*p == 'E') || (*p == 'e')) {
13815 p++;
13816 goto after_exp;
13817 } else if ((*p != '_') ||
13818 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13819 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13820 }
13821 }
13822
13823 } else if (('0' <= *p) && (*p <= '9')) {
13824 if (*p == '0') {
13825 for (; (p < q) && (*p == '0'); p++) {
13826 }
13827 } else {
13828 h->digits[nd++] = (uint8_t)(*p - '0');
13829 dp = (int32_t)nd;
13830 p++;
13831 }
13832
13833 for (;; p++) {
13834 if (p >= q) {
13835 goto after_all;
13836 } else if (('0' <= *p) && (*p <= '9')) {
13837 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13838 h->digits[nd++] = (uint8_t)(*p - '0');
13839 dp = (int32_t)nd;
13840 } else if ('0' != *p) {
13841 // Long-tail non-zeroes set the truncated bit.
13842 h->truncated = true;
13843 }
13844 } else if (*p ==
13845 ((options &
13846 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13847 ? ','
13848 : '.')) {
13849 p++;
13850 goto after_sep;
13851 } else if ((*p == 'E') || (*p == 'e')) {
13852 p++;
13853 goto after_exp;
13854 } else if ((*p != '_') ||
13855 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13856 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13857 }
13858 }
13859
13860 } else if (*p == ((options &
13861 WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
13862 ? ','
13863 : '.')) {
13864 p++;
13865 no_digits_before_separator = true;
13866
13867 } else {
13868 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13869 }
13870
13871after_sep:
13872 for (;; p++) {
13873 if (p >= q) {
13874 goto after_all;
13875 } else if ('0' == *p) {
13876 if (nd == 0) {
13877 // Track leading zeroes implicitly.
13878 dp--;
13879 } else if (nd <
13880 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13881 h->digits[nd++] = (uint8_t)(*p - '0');
13882 }
13883 } else if (('0' < *p) && (*p <= '9')) {
13884 if (nd < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
13885 h->digits[nd++] = (uint8_t)(*p - '0');
13886 } else {
13887 // Long-tail non-zeroes set the truncated bit.
13888 h->truncated = true;
13889 }
13890 } else if ((*p == 'E') || (*p == 'e')) {
13891 p++;
13892 goto after_exp;
13893 } else if ((*p != '_') ||
13894 !(options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13895 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13896 }
13897 }
13898
13899after_exp:
13900 do {
13901 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
13902 for (;; p++) {
13903 if (p >= q) {
13904 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13905 } else if (*p != '_') {
13906 break;
13907 }
13908 }
13909 }
13910
13911 int32_t exp_sign = +1;
13912 if (*p == '+') {
13913 p++;
13914 } else if (*p == '-') {
13915 exp_sign = -1;
13916 p++;
13917 }
13918
13919 int32_t exp = 0;
13920 const int32_t exp_large =
13921 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE +
13922 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
13923 bool saw_exp_digits = false;
13924 for (; p < q; p++) {
13925 if ((*p == '_') &&
13926 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
13927 // No-op.
13928 } else if (('0' <= *p) && (*p <= '9')) {
13929 saw_exp_digits = true;
13930 if (exp < exp_large) {
13931 exp = (10 * exp) + ((int32_t)(*p - '0'));
13932 }
13933 } else {
13934 break;
13935 }
13936 }
13937 if (!saw_exp_digits) {
13938 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13939 }
13940 dp += exp_sign * exp;
13941 } while (0);
13942
13943after_all:
13944 if (p != q) {
13945 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13946 }
13947 h->num_digits = nd;
13948 if (nd == 0) {
13949 if (no_digits_before_separator) {
13950 return wuffs_base__make_status(wuffs_base__error__bad_argument);
13951 }
13952 h->decimal_point = 0;
13953 } else if (dp <
13954 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
13955 h->decimal_point =
13956 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE - 1;
13957 } else if (dp >
13958 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
13959 h->decimal_point =
13960 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE + 1;
13961 } else {
13962 h->decimal_point = dp;
13963 }
13964 wuffs_base__private_implementation__high_prec_dec__trim(h);
13965 return wuffs_base__make_status(NULL);
13966}
13967
13968// --------
13969
13970// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
13971// returns the number of additional decimal digits when left-shifting by shift.
13972//
13973// See below for preconditions.
13974static uint32_t //
13975wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
13976 wuffs_base__private_implementation__high_prec_dec* h,
13977 uint32_t shift) {
13978 // Masking with 0x3F should be unnecessary (assuming the preconditions) but
13979 // it's cheap and ensures that we don't overflow the
13980 // wuffs_base__private_implementation__hpd_left_shift array.
13981 shift &= 63;
13982
13983 uint32_t x_a = wuffs_base__private_implementation__hpd_left_shift[shift];
13984 uint32_t x_b = wuffs_base__private_implementation__hpd_left_shift[shift + 1];
13985 uint32_t num_new_digits = x_a >> 11;
13986 uint32_t pow5_a = 0x7FF & x_a;
13987 uint32_t pow5_b = 0x7FF & x_b;
13988
13989 const uint8_t* pow5 =
13990 &wuffs_base__private_implementation__powers_of_5[pow5_a];
13991 uint32_t i = 0;
13992 uint32_t n = pow5_b - pow5_a;
13993 for (; i < n; i++) {
13994 if (i >= h->num_digits) {
13995 return num_new_digits - 1;
13996 } else if (h->digits[i] == pow5[i]) {
13997 continue;
13998 } else if (h->digits[i] < pow5[i]) {
13999 return num_new_digits - 1;
14000 } else {
14001 return num_new_digits;
14002 }
14003 }
14004 return num_new_digits;
14005}
14006
14007// --------
14008
14009// wuffs_base__private_implementation__high_prec_dec__rounded_integer returns
14010// the integral (non-fractional) part of h, provided that it is 18 or fewer
14011// decimal digits. For 19 or more digits, it returns UINT64_MAX. Note that:
Nigel Taobf9dab32021-11-18 19:19:55 +110014012// - (1 << 53) is 9007199254740992, which has 16 decimal digits.
14013// - (1 << 56) is 72057594037927936, which has 17 decimal digits.
14014// - (1 << 59) is 576460752303423488, which has 18 decimal digits.
14015// - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
Nigel Taoe360a532021-04-05 22:47:03 +100014016// and that IEEE 754 double precision has 52 mantissa bits.
14017//
14018// That integral part is rounded-to-even: rounding 7.5 or 8.5 both give 8.
14019//
14020// h's negative bit is ignored: rounding -8.6 returns 9.
14021//
14022// See below for preconditions.
14023static uint64_t //
14024wuffs_base__private_implementation__high_prec_dec__rounded_integer(
14025 wuffs_base__private_implementation__high_prec_dec* h) {
14026 if ((h->num_digits == 0) || (h->decimal_point < 0)) {
14027 return 0;
14028 } else if (h->decimal_point > 18) {
14029 return UINT64_MAX;
14030 }
14031
14032 uint32_t dp = (uint32_t)(h->decimal_point);
14033 uint64_t n = 0;
14034 uint32_t i = 0;
14035 for (; i < dp; i++) {
14036 n = (10 * n) + ((i < h->num_digits) ? h->digits[i] : 0);
14037 }
14038
14039 bool round_up = false;
14040 if (dp < h->num_digits) {
14041 round_up = h->digits[dp] >= 5;
14042 if ((h->digits[dp] == 5) && (dp + 1 == h->num_digits)) {
14043 // We are exactly halfway. If we're truncated, round up, otherwise round
14044 // to even.
14045 round_up = h->truncated || //
14046 ((dp > 0) && (1 & h->digits[dp - 1]));
14047 }
14048 }
14049 if (round_up) {
14050 n++;
14051 }
14052
14053 return n;
14054}
14055
14056// wuffs_base__private_implementation__high_prec_dec__small_xshift shifts h's
14057// number (where 'x' is 'l' or 'r' for left or right) by a small shift value.
14058//
14059// Preconditions:
14060// - h is non-NULL.
14061// - h->decimal_point is "not extreme".
14062// - shift is non-zero.
14063// - shift is "a small shift".
14064//
14065// "Not extreme" means within
14066// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
14067//
14068// "A small shift" means not more than
14069// WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
14070//
14071// wuffs_base__private_implementation__high_prec_dec__rounded_integer and
14072// wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits
14073// have the same preconditions.
14074//
14075// wuffs_base__private_implementation__high_prec_dec__lshift keeps the first
14076// two preconditions but not the last two. Its shift argument is signed and
14077// does not need to be "small": zero is a no-op, positive means left shift and
14078// negative means right shift.
14079
14080static void //
14081wuffs_base__private_implementation__high_prec_dec__small_lshift(
14082 wuffs_base__private_implementation__high_prec_dec* h,
14083 uint32_t shift) {
14084 if (h->num_digits == 0) {
14085 return;
14086 }
14087 uint32_t num_new_digits =
14088 wuffs_base__private_implementation__high_prec_dec__lshift_num_new_digits(
14089 h, shift);
14090 uint32_t rx = h->num_digits - 1; // Read index.
14091 uint32_t wx = h->num_digits - 1 + num_new_digits; // Write index.
14092 uint64_t n = 0;
14093
14094 // Repeat: pick up a digit, put down a digit, right to left.
14095 while (((int32_t)rx) >= 0) {
14096 n += ((uint64_t)(h->digits[rx])) << shift;
14097 uint64_t quo = n / 10;
14098 uint64_t rem = n - (10 * quo);
14099 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
14100 h->digits[wx] = (uint8_t)rem;
14101 } else if (rem > 0) {
14102 h->truncated = true;
14103 }
14104 n = quo;
14105 wx--;
14106 rx--;
14107 }
14108
14109 // Put down leading digits, right to left.
14110 while (n > 0) {
14111 uint64_t quo = n / 10;
14112 uint64_t rem = n - (10 * quo);
14113 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
14114 h->digits[wx] = (uint8_t)rem;
14115 } else if (rem > 0) {
14116 h->truncated = true;
14117 }
14118 n = quo;
14119 wx--;
14120 }
14121
14122 // Finish.
14123 h->num_digits += num_new_digits;
14124 if (h->num_digits >
14125 WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
14126 h->num_digits = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION;
14127 }
14128 h->decimal_point += (int32_t)num_new_digits;
14129 wuffs_base__private_implementation__high_prec_dec__trim(h);
14130}
14131
14132static void //
14133wuffs_base__private_implementation__high_prec_dec__small_rshift(
14134 wuffs_base__private_implementation__high_prec_dec* h,
14135 uint32_t shift) {
14136 uint32_t rx = 0; // Read index.
14137 uint32_t wx = 0; // Write index.
14138 uint64_t n = 0;
14139
14140 // Pick up enough leading digits to cover the first shift.
14141 while ((n >> shift) == 0) {
14142 if (rx < h->num_digits) {
14143 // Read a digit.
14144 n = (10 * n) + h->digits[rx++];
14145 } else if (n == 0) {
14146 // h's number used to be zero and remains zero.
14147 return;
14148 } else {
14149 // Read sufficient implicit trailing zeroes.
14150 while ((n >> shift) == 0) {
14151 n = 10 * n;
14152 rx++;
14153 }
14154 break;
14155 }
14156 }
14157 h->decimal_point -= ((int32_t)(rx - 1));
14158 if (h->decimal_point <
14159 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
14160 // After the shift, h's number is effectively zero.
14161 h->num_digits = 0;
14162 h->decimal_point = 0;
14163 h->truncated = false;
14164 return;
14165 }
14166
14167 // Repeat: pick up a digit, put down a digit, left to right.
14168 uint64_t mask = (((uint64_t)(1)) << shift) - 1;
14169 while (rx < h->num_digits) {
14170 uint8_t new_digit = ((uint8_t)(n >> shift));
14171 n = (10 * (n & mask)) + h->digits[rx++];
14172 h->digits[wx++] = new_digit;
14173 }
14174
14175 // Put down trailing digits, left to right.
14176 while (n > 0) {
14177 uint8_t new_digit = ((uint8_t)(n >> shift));
14178 n = 10 * (n & mask);
14179 if (wx < WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DIGITS_PRECISION) {
14180 h->digits[wx++] = new_digit;
14181 } else if (new_digit > 0) {
14182 h->truncated = true;
14183 }
14184 }
14185
14186 // Finish.
14187 h->num_digits = wx;
14188 wuffs_base__private_implementation__high_prec_dec__trim(h);
14189}
14190
14191static void //
14192wuffs_base__private_implementation__high_prec_dec__lshift(
14193 wuffs_base__private_implementation__high_prec_dec* h,
14194 int32_t shift) {
14195 if (shift > 0) {
14196 while (shift > +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
14197 wuffs_base__private_implementation__high_prec_dec__small_lshift(
14198 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
14199 shift -= WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14200 }
14201 wuffs_base__private_implementation__high_prec_dec__small_lshift(
14202 h, ((uint32_t)(+shift)));
14203 } else if (shift < 0) {
14204 while (shift < -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
14205 wuffs_base__private_implementation__high_prec_dec__small_rshift(
14206 h, WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL);
14207 shift += WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14208 }
14209 wuffs_base__private_implementation__high_prec_dec__small_rshift(
14210 h, ((uint32_t)(-shift)));
14211 }
14212}
14213
14214// --------
14215
14216// wuffs_base__private_implementation__high_prec_dec__round_etc rounds h's
14217// number. For those functions that take an n argument, rounding produces at
14218// most n digits (which is not necessarily at most n decimal places). Negative
14219// n values are ignored, as well as any n greater than or equal to h's number
14220// of digits. The etc__round_just_enough function implicitly chooses an n to
14221// implement WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION.
14222//
14223// Preconditions:
14224// - h is non-NULL.
14225// - h->decimal_point is "not extreme".
14226//
14227// "Not extreme" means within
14228// ±WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE.
14229
14230static void //
14231wuffs_base__private_implementation__high_prec_dec__round_down(
14232 wuffs_base__private_implementation__high_prec_dec* h,
14233 int32_t n) {
14234 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
14235 return;
14236 }
14237 h->num_digits = (uint32_t)(n);
14238 wuffs_base__private_implementation__high_prec_dec__trim(h);
14239}
14240
14241static void //
14242wuffs_base__private_implementation__high_prec_dec__round_up(
14243 wuffs_base__private_implementation__high_prec_dec* h,
14244 int32_t n) {
14245 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
14246 return;
14247 }
14248
14249 for (n--; n >= 0; n--) {
14250 if (h->digits[n] < 9) {
14251 h->digits[n]++;
14252 h->num_digits = (uint32_t)(n + 1);
14253 return;
14254 }
14255 }
14256
14257 // The number is all 9s. Change to a single 1 and adjust the decimal point.
14258 h->digits[0] = 1;
14259 h->num_digits = 1;
14260 h->decimal_point++;
14261}
14262
14263static void //
14264wuffs_base__private_implementation__high_prec_dec__round_nearest(
14265 wuffs_base__private_implementation__high_prec_dec* h,
14266 int32_t n) {
14267 if ((n < 0) || (h->num_digits <= (uint32_t)n)) {
14268 return;
14269 }
14270 bool up = h->digits[n] >= 5;
14271 if ((h->digits[n] == 5) && ((n + 1) == ((int32_t)(h->num_digits)))) {
14272 up = h->truncated || //
14273 ((n > 0) && ((h->digits[n - 1] & 1) != 0));
14274 }
14275
14276 if (up) {
14277 wuffs_base__private_implementation__high_prec_dec__round_up(h, n);
14278 } else {
14279 wuffs_base__private_implementation__high_prec_dec__round_down(h, n);
14280 }
14281}
14282
14283static void //
14284wuffs_base__private_implementation__high_prec_dec__round_just_enough(
14285 wuffs_base__private_implementation__high_prec_dec* h,
14286 int32_t exp2,
14287 uint64_t mantissa) {
14288 // The magic numbers 52 and 53 in this function are because IEEE 754 double
14289 // precision has 52 mantissa bits.
14290 //
14291 // Let f be the floating point number represented by exp2 and mantissa (and
14292 // also the number in h): the number (mantissa * (2 ** (exp2 - 52))).
14293 //
14294 // If f is zero or a small integer, we can return early.
14295 if ((mantissa == 0) ||
14296 ((exp2 < 53) && (h->decimal_point >= ((int32_t)(h->num_digits))))) {
14297 return;
14298 }
14299
14300 // The smallest normal f has an exp2 of -1022 and a mantissa of (1 << 52).
14301 // Subnormal numbers have the same exp2 but a smaller mantissa.
14302 static const int32_t min_incl_normal_exp2 = -1022;
14303 static const uint64_t min_incl_normal_mantissa = 0x0010000000000000ul;
14304
14305 // Compute lower and upper bounds such that any number between them (possibly
14306 // inclusive) will round to f. First, the lower bound. Our number f is:
14307 // ((mantissa + 0) * (2 ** ( exp2 - 52)))
14308 //
14309 // The next lowest floating point number is:
14310 // ((mantissa - 1) * (2 ** ( exp2 - 52)))
14311 // unless (mantissa - 1) drops the (1 << 52) bit and exp2 is not the
14312 // min_incl_normal_exp2. Either way, call it:
14313 // ((l_mantissa) * (2 ** (l_exp2 - 52)))
14314 //
14315 // The lower bound is halfway between them (noting that 52 became 53):
14316 // (((2 * l_mantissa) + 1) * (2 ** (l_exp2 - 53)))
14317 int32_t l_exp2 = exp2;
14318 uint64_t l_mantissa = mantissa - 1;
14319 if ((exp2 > min_incl_normal_exp2) && (mantissa <= min_incl_normal_mantissa)) {
14320 l_exp2 = exp2 - 1;
14321 l_mantissa = (2 * mantissa) - 1;
14322 }
14323 wuffs_base__private_implementation__high_prec_dec lower;
14324 wuffs_base__private_implementation__high_prec_dec__assign(
14325 &lower, (2 * l_mantissa) + 1, false);
14326 wuffs_base__private_implementation__high_prec_dec__lshift(&lower,
14327 l_exp2 - 53);
14328
14329 // Next, the upper bound. Our number f is:
14330 // ((mantissa + 0) * (2 ** (exp2 - 52)))
14331 //
14332 // The next highest floating point number is:
14333 // ((mantissa + 1) * (2 ** (exp2 - 52)))
14334 //
14335 // The upper bound is halfway between them (noting that 52 became 53):
14336 // (((2 * mantissa) + 1) * (2 ** (exp2 - 53)))
14337 wuffs_base__private_implementation__high_prec_dec upper;
14338 wuffs_base__private_implementation__high_prec_dec__assign(
14339 &upper, (2 * mantissa) + 1, false);
14340 wuffs_base__private_implementation__high_prec_dec__lshift(&upper, exp2 - 53);
14341
14342 // The lower and upper bounds are possible outputs only if the original
14343 // mantissa is even, so that IEEE round-to-even would round to the original
14344 // mantissa and not its neighbors.
14345 bool inclusive = (mantissa & 1) == 0;
14346
14347 // As we walk the digits, we want to know whether rounding up would fall
14348 // within the upper bound. This is tracked by upper_delta:
14349 // - When -1, the digits of h and upper are the same so far.
14350 // - When +0, we saw a difference of 1 between h and upper on a previous
14351 // digit and subsequently only 9s for h and 0s for upper. Thus, rounding
14352 // up may fall outside of the bound if !inclusive.
14353 // - When +1, the difference is greater than 1 and we know that rounding up
14354 // falls within the bound.
14355 //
14356 // This is a state machine with three states. The numerical value for each
14357 // state (-1, +0 or +1) isn't important, other than their order.
14358 int upper_delta = -1;
14359
14360 // We can now figure out the shortest number of digits required. Walk the
14361 // digits until h has distinguished itself from lower or upper.
14362 //
14363 // The zi and zd variables are indexes and digits, for z in l (lower), h (the
14364 // number) and u (upper).
14365 //
14366 // The lower, h and upper numbers may have their decimal points at different
14367 // places. In this case, upper is the longest, so we iterate ui starting from
14368 // 0 and iterate li and hi starting from either 0 or -1.
14369 int32_t ui = 0;
14370 for (;; ui++) {
14371 // Calculate hd, the middle number's digit.
14372 int32_t hi = ui - upper.decimal_point + h->decimal_point;
14373 if (hi >= ((int32_t)(h->num_digits))) {
14374 break;
14375 }
14376 uint8_t hd = (((uint32_t)hi) < h->num_digits) ? h->digits[hi] : 0;
14377
14378 // Calculate ld, the lower bound's digit.
14379 int32_t li = ui - upper.decimal_point + lower.decimal_point;
14380 uint8_t ld = (((uint32_t)li) < lower.num_digits) ? lower.digits[li] : 0;
14381
14382 // We can round down (truncate) if lower has a different digit than h or if
14383 // lower is inclusive and is exactly the result of rounding down (i.e. we
14384 // have reached the final digit of lower).
14385 bool can_round_down =
14386 (ld != hd) || //
14387 (inclusive && ((li + 1) == ((int32_t)(lower.num_digits))));
14388
14389 // Calculate ud, the upper bound's digit, and update upper_delta.
14390 uint8_t ud = (((uint32_t)ui) < upper.num_digits) ? upper.digits[ui] : 0;
14391 if (upper_delta < 0) {
14392 if ((hd + 1) < ud) {
14393 // For example:
14394 // h = 12345???
14395 // upper = 12347???
14396 upper_delta = +1;
14397 } else if (hd != ud) {
14398 // For example:
14399 // h = 12345???
14400 // upper = 12346???
14401 upper_delta = +0;
14402 }
14403 } else if (upper_delta == 0) {
14404 if ((hd != 9) || (ud != 0)) {
14405 // For example:
14406 // h = 1234598?
14407 // upper = 1234600?
14408 upper_delta = +1;
14409 }
14410 }
14411
14412 // We can round up if upper has a different digit than h and either upper
14413 // is inclusive or upper is bigger than the result of rounding up.
14414 bool can_round_up =
14415 (upper_delta > 0) || //
14416 ((upper_delta == 0) && //
14417 (inclusive || ((ui + 1) < ((int32_t)(upper.num_digits)))));
14418
14419 // If we can round either way, round to nearest. If we can round only one
14420 // way, do it. If we can't round, continue the loop.
14421 if (can_round_down) {
14422 if (can_round_up) {
14423 wuffs_base__private_implementation__high_prec_dec__round_nearest(
14424 h, hi + 1);
14425 return;
14426 } else {
14427 wuffs_base__private_implementation__high_prec_dec__round_down(h,
14428 hi + 1);
14429 return;
14430 }
14431 } else {
14432 if (can_round_up) {
14433 wuffs_base__private_implementation__high_prec_dec__round_up(h, hi + 1);
14434 return;
14435 }
14436 }
14437 }
14438}
14439
14440// --------
14441
14442// wuffs_base__private_implementation__parse_number_f64_eisel_lemire produces
14443// the IEEE 754 double-precision value for an exact mantissa and base-10
14444// exponent. For example:
14445// - when parsing "12345.678e+02", man is 12345678 and exp10 is -1.
14446// - when parsing "-12", man is 12 and exp10 is 0. Processing the leading
14447// minus sign is the responsibility of the caller, not this function.
14448//
14449// On success, it returns a non-negative int64_t such that the low 63 bits hold
14450// the 11-bit exponent and 52-bit mantissa.
14451//
14452// On failure, it returns a negative value.
14453//
14454// The algorithm is based on an original idea by Michael Eisel that was refined
14455// by Daniel Lemire. See
14456// https://lemire.me/blog/2020/03/10/fast-float-parsing-in-practice/
14457// and
14458// https://nigeltao.github.io/blog/2020/eisel-lemire.html
14459//
14460// Preconditions:
14461// - man is non-zero.
14462// - exp10 is in the range [-307 ..= 288], the same range of the
14463// wuffs_base__private_implementation__powers_of_10 array.
14464//
14465// The exp10 range (and the fact that man is in the range [1 ..= UINT64_MAX],
14466// approximately [1 ..= 1.85e+19]) means that (man * (10 ** exp10)) is in the
14467// range [1e-307 ..= 1.85e+307]. This is entirely within the range of normal
14468// (neither subnormal nor non-finite) f64 values: DBL_MIN and DBL_MAX are
14469// approximately 2.23e–308 and 1.80e+308.
14470static int64_t //
14471wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
14472 uint64_t man,
14473 int32_t exp10) {
14474 // Look up the (possibly truncated) base-2 representation of (10 ** exp10).
14475 // The look-up table was constructed so that it is already normalized: the
14476 // table entry's mantissa's MSB (most significant bit) is on.
14477 const uint64_t* po10 =
14478 &wuffs_base__private_implementation__powers_of_10[exp10 + 307][0];
14479
14480 // Normalize the man argument. The (man != 0) precondition means that a
14481 // non-zero bit exists.
14482 uint32_t clz = wuffs_base__count_leading_zeroes_u64(man);
14483 man <<= clz;
14484
14485 // Calculate the return value's base-2 exponent. We might tweak it by ±1
14486 // later, but its initial value comes from a linear scaling of exp10,
14487 // converting from power-of-10 to power-of-2, and adjusting by clz.
14488 //
14489 // The magic constants are:
14490 // - 1087 = 1023 + 64. The 1023 is the f64 exponent bias. The 64 is because
14491 // the look-up table uses 64-bit mantissas.
14492 // - 217706 is such that the ratio 217706 / 65536 ≈ 3.321930 is close enough
14493 // (over the practical range of exp10) to log(10) / log(2) ≈ 3.321928.
14494 // - 65536 = 1<<16 is arbitrary but a power of 2, so division is a shift.
14495 //
14496 // Equality of the linearly-scaled value and the actual power-of-2, over the
14497 // range of exp10 arguments that this function accepts, is confirmed by
14498 // script/print-mpb-powers-of-10.go
14499 uint64_t ret_exp2 =
14500 ((uint64_t)(((217706 * exp10) >> 16) + 1087)) - ((uint64_t)clz);
14501
14502 // Multiply the two mantissas. Normalization means that both mantissas are at
14503 // least (1<<63), so the 128-bit product must be at least (1<<126). The high
14504 // 64 bits of the product, x_hi, must therefore be at least (1<<62).
14505 //
14506 // As a consequence, x_hi has either 0 or 1 leading zeroes. Shifting x_hi
14507 // right by either 9 or 10 bits (depending on x_hi's MSB) will therefore
14508 // leave the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on.
14509 wuffs_base__multiply_u64__output x = wuffs_base__multiply_u64(man, po10[1]);
14510 uint64_t x_hi = x.hi;
14511 uint64_t x_lo = x.lo;
14512
14513 // Before we shift right by at least 9 bits, recall that the look-up table
14514 // entry was possibly truncated. We have so far only calculated a lower bound
14515 // for the product (man * e), where e is (10 ** exp10). The upper bound would
14516 // add a further (man * 1) to the 128-bit product, which overflows the lower
14517 // 64-bit limb if ((x_lo + man) < man).
14518 //
14519 // If overflow occurs, that adds 1 to x_hi. Since we're about to shift right
14520 // by at least 9 bits, that carried 1 can be ignored unless the higher 64-bit
14521 // limb's low 9 bits are all on.
14522 //
14523 // For example, parsing "9999999999999999999" will take the if-true branch
14524 // here, since:
14525 // - x_hi = 0x4563918244F3FFFF
14526 // - x_lo = 0x8000000000000000
14527 // - man = 0x8AC7230489E7FFFF
14528 if (((x_hi & 0x1FF) == 0x1FF) && ((x_lo + man) < man)) {
14529 // Refine our calculation of (man * e). Before, our approximation of e used
14530 // a "low resolution" 64-bit mantissa. Now use a "high resolution" 128-bit
14531 // mantissa. We've already calculated x = (man * bits_0_to_63_incl_of_e).
14532 // Now calculate y = (man * bits_64_to_127_incl_of_e).
14533 wuffs_base__multiply_u64__output y = wuffs_base__multiply_u64(man, po10[0]);
14534 uint64_t y_hi = y.hi;
14535 uint64_t y_lo = y.lo;
14536
14537 // Merge the 128-bit x and 128-bit y, which overlap by 64 bits, to
14538 // calculate the 192-bit product of the 64-bit man by the 128-bit e.
14539 // As we exit this if-block, we only care about the high 128 bits
14540 // (merged_hi and merged_lo) of that 192-bit product.
14541 //
14542 // For example, parsing "1.234e-45" will take the if-true branch here,
14543 // since:
14544 // - x_hi = 0x70B7E3696DB29FFF
14545 // - x_lo = 0xE040000000000000
14546 // - y_hi = 0x33718BBEAB0E0D7A
14547 // - y_lo = 0xA880000000000000
14548 uint64_t merged_hi = x_hi;
14549 uint64_t merged_lo = x_lo + y_hi;
14550 if (merged_lo < x_lo) {
14551 merged_hi++; // Carry the overflow bit.
14552 }
14553
14554 // The "high resolution" approximation of e is still a lower bound. Once
14555 // again, see if the upper bound is large enough to produce a different
14556 // result. This time, if it does, give up instead of reaching for an even
14557 // more precise approximation to e.
14558 //
14559 // This three-part check is similar to the two-part check that guarded the
14560 // if block that we're now in, but it has an extra term for the middle 64
14561 // bits (checking that adding 1 to merged_lo would overflow).
14562 //
14563 // For example, parsing "5.9604644775390625e-8" will take the if-true
14564 // branch here, since:
14565 // - merged_hi = 0x7FFFFFFFFFFFFFFF
14566 // - merged_lo = 0xFFFFFFFFFFFFFFFF
14567 // - y_lo = 0x4DB3FFC120988200
14568 // - man = 0xD3C21BCECCEDA100
14569 if (((merged_hi & 0x1FF) == 0x1FF) && ((merged_lo + 1) == 0) &&
14570 (y_lo + man < man)) {
14571 return -1;
14572 }
14573
14574 // Replace the 128-bit x with merged.
14575 x_hi = merged_hi;
14576 x_lo = merged_lo;
14577 }
14578
14579 // As mentioned above, shifting x_hi right by either 9 or 10 bits will leave
14580 // the top 10 MSBs (bits 54 ..= 63) off and the 11th MSB (bit 53) on. If the
14581 // MSB (before shifting) was on, adjust ret_exp2 for the larger shift.
14582 //
14583 // Having bit 53 on (and higher bits off) means that ret_mantissa is a 54-bit
14584 // number.
14585 uint64_t msb = x_hi >> 63;
14586 uint64_t ret_mantissa = x_hi >> (msb + 9);
14587 ret_exp2 -= 1 ^ msb;
14588
14589 // IEEE 754 rounds to-nearest with ties rounded to-even. Rounding to-even can
14590 // be tricky. If we're half-way between two exactly representable numbers
14591 // (x's low 73 bits are zero and the next 2 bits that matter are "01"), give
14592 // up instead of trying to pick the winner.
14593 //
14594 // Technically, we could tighten the condition by changing "73" to "73 or 74,
14595 // depending on msb", but a flat "73" is simpler.
14596 //
14597 // For example, parsing "1e+23" will take the if-true branch here, since:
14598 // - x_hi = 0x54B40B1F852BDA00
14599 // - ret_mantissa = 0x002A5A058FC295ED
14600 if ((x_lo == 0) && ((x_hi & 0x1FF) == 0) && ((ret_mantissa & 3) == 1)) {
14601 return -1;
14602 }
14603
14604 // If we're not halfway then it's rounding to-nearest. Starting with a 54-bit
14605 // number, carry the lowest bit (bit 0) up if it's on. Regardless of whether
14606 // it was on or off, shifting right by one then produces a 53-bit number. If
14607 // carrying up overflowed, shift again.
14608 ret_mantissa += ret_mantissa & 1;
14609 ret_mantissa >>= 1;
14610 // This if block is equivalent to (but benchmarks slightly faster than) the
14611 // following branchless form:
14612 // uint64_t overflow_adjustment = ret_mantissa >> 53;
14613 // ret_mantissa >>= overflow_adjustment;
14614 // ret_exp2 += overflow_adjustment;
14615 //
14616 // For example, parsing "7.2057594037927933e+16" will take the if-true
14617 // branch here, since:
14618 // - x_hi = 0x7FFFFFFFFFFFFE80
14619 // - ret_mantissa = 0x0020000000000000
14620 if ((ret_mantissa >> 53) > 0) {
14621 ret_mantissa >>= 1;
14622 ret_exp2++;
14623 }
14624
14625 // Starting with a 53-bit number, IEEE 754 double-precision normal numbers
14626 // have an implicit mantissa bit. Mask that away and keep the low 52 bits.
14627 ret_mantissa &= 0x000FFFFFFFFFFFFF;
14628
14629 // Pack the bits and return.
14630 return ((int64_t)(ret_mantissa | (ret_exp2 << 52)));
14631}
14632
14633// --------
14634
14635static wuffs_base__result_f64 //
14636wuffs_base__private_implementation__parse_number_f64_special(
14637 wuffs_base__slice_u8 s,
14638 uint32_t options) {
14639 do {
14640 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
14641 goto fail;
14642 }
14643
14644 uint8_t* p = s.ptr;
14645 uint8_t* q = s.ptr + s.len;
14646
14647 for (; (p < q) && (*p == '_'); p++) {
14648 }
14649 if (p >= q) {
14650 goto fail;
14651 }
14652
14653 // Parse sign.
14654 bool negative = false;
14655 do {
14656 if (*p == '+') {
14657 p++;
14658 } else if (*p == '-') {
14659 negative = true;
14660 p++;
14661 } else {
14662 break;
14663 }
14664 for (; (p < q) && (*p == '_'); p++) {
14665 }
14666 } while (0);
14667 if (p >= q) {
14668 goto fail;
14669 }
14670
14671 bool nan = false;
14672 switch (p[0]) {
14673 case 'I':
14674 case 'i':
14675 if (((q - p) < 3) || //
14676 ((p[1] != 'N') && (p[1] != 'n')) || //
14677 ((p[2] != 'F') && (p[2] != 'f'))) {
14678 goto fail;
14679 }
14680 p += 3;
14681
14682 if ((p >= q) || (*p == '_')) {
14683 break;
14684 } else if (((q - p) < 5) || //
14685 ((p[0] != 'I') && (p[0] != 'i')) || //
14686 ((p[1] != 'N') && (p[1] != 'n')) || //
14687 ((p[2] != 'I') && (p[2] != 'i')) || //
14688 ((p[3] != 'T') && (p[3] != 't')) || //
14689 ((p[4] != 'Y') && (p[4] != 'y'))) {
14690 goto fail;
14691 }
14692 p += 5;
14693
14694 if ((p >= q) || (*p == '_')) {
14695 break;
14696 }
14697 goto fail;
14698
14699 case 'N':
14700 case 'n':
14701 if (((q - p) < 3) || //
14702 ((p[1] != 'A') && (p[1] != 'a')) || //
14703 ((p[2] != 'N') && (p[2] != 'n'))) {
14704 goto fail;
14705 }
14706 p += 3;
14707
14708 if ((p >= q) || (*p == '_')) {
14709 nan = true;
14710 break;
14711 }
14712 goto fail;
14713
14714 default:
14715 goto fail;
14716 }
14717
14718 // Finish.
14719 for (; (p < q) && (*p == '_'); p++) {
14720 }
14721 if (p != q) {
14722 goto fail;
14723 }
14724 wuffs_base__result_f64 ret;
14725 ret.status.repr = NULL;
14726 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
14727 (nan ? 0x7FFFFFFFFFFFFFFF : 0x7FF0000000000000) |
14728 (negative ? 0x8000000000000000 : 0));
14729 return ret;
14730 } while (0);
14731
14732fail:
14733 do {
14734 wuffs_base__result_f64 ret;
14735 ret.status.repr = wuffs_base__error__bad_argument;
14736 ret.value = 0;
14737 return ret;
14738 } while (0);
14739}
14740
14741WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
14742wuffs_base__private_implementation__high_prec_dec__to_f64(
14743 wuffs_base__private_implementation__high_prec_dec* h,
14744 uint32_t options) {
14745 do {
14746 // powers converts decimal powers of 10 to binary powers of 2. For example,
14747 // (10000 >> 13) is 1. It stops before the elements exceed 60, also known
14748 // as WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL.
14749 static const uint32_t num_powers = 19;
14750 static const uint8_t powers[19] = {
14751 0, 3, 6, 9, 13, 16, 19, 23, 26, 29, //
14752 33, 36, 39, 43, 46, 49, 53, 56, 59, //
14753 };
14754
14755 // Handle zero and obvious extremes. The largest and smallest positive
14756 // finite f64 values are approximately 1.8e+308 and 4.9e-324.
14757 if ((h->num_digits == 0) || (h->decimal_point < -326)) {
14758 goto zero;
14759 } else if (h->decimal_point > 310) {
14760 goto infinity;
14761 }
14762
14763 // Try the fast Eisel-Lemire algorithm again. Calculating the (man, exp10)
14764 // pair from the high_prec_dec h is more correct but slower than the
14765 // approach taken in wuffs_base__parse_number_f64. The latter is optimized
14766 // for the common cases (e.g. assuming no underscores or a leading '+'
14767 // sign) rather than the full set of cases allowed by the Wuffs API.
14768 if (h->num_digits <= 19) {
14769 uint64_t man = 0;
14770 uint32_t i;
14771 for (i = 0; i < h->num_digits; i++) {
14772 man = (10 * man) + h->digits[i];
14773 }
14774 int32_t exp10 = h->decimal_point - ((int32_t)(h->num_digits));
14775 if ((man != 0) && (-307 <= exp10) && (exp10 <= 288)) {
14776 int64_t r =
14777 wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
14778 man, exp10);
14779 if (r >= 0) {
14780 wuffs_base__result_f64 ret;
14781 ret.status.repr = NULL;
14782 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
14783 ((uint64_t)r) | (((uint64_t)(h->negative)) << 63));
14784 return ret;
14785 }
14786 }
14787 }
14788
14789 // When Eisel-Lemire fails, fall back to Simple Decimal Conversion. See
14790 // https://nigeltao.github.io/blog/2020/parse-number-f64-simple.html
14791 //
14792 // Scale by powers of 2 until we're in the range [½ .. 1], which gives us
14793 // our exponent (in base-2). First we shift right, possibly a little too
14794 // far, ending with a value certainly below 1 and possibly below ½...
14795 const int32_t f64_bias = -1023;
14796 int32_t exp2 = 0;
14797 while (h->decimal_point > 0) {
14798 uint32_t n = (uint32_t)(+h->decimal_point);
14799 uint32_t shift =
14800 (n < num_powers)
14801 ? powers[n]
14802 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14803
14804 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, shift);
14805 if (h->decimal_point <
14806 -WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
14807 goto zero;
14808 }
14809 exp2 += (int32_t)shift;
14810 }
14811 // ...then we shift left, putting us in [½ .. 1].
14812 while (h->decimal_point <= 0) {
14813 uint32_t shift;
14814 if (h->decimal_point == 0) {
14815 if (h->digits[0] >= 5) {
14816 break;
14817 }
14818 shift = (h->digits[0] < 2) ? 2 : 1;
14819 } else {
14820 uint32_t n = (uint32_t)(-h->decimal_point);
14821 shift = (n < num_powers)
14822 ? powers[n]
14823 : WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14824 }
14825
14826 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, shift);
14827 if (h->decimal_point >
14828 +WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__DECIMAL_POINT__RANGE) {
14829 goto infinity;
14830 }
14831 exp2 -= (int32_t)shift;
14832 }
14833
14834 // We're in the range [½ .. 1] but f64 uses [1 .. 2].
14835 exp2--;
14836
14837 // The minimum normal exponent is (f64_bias + 1).
14838 while ((f64_bias + 1) > exp2) {
14839 uint32_t n = (uint32_t)((f64_bias + 1) - exp2);
14840 if (n > WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL) {
14841 n = WUFFS_BASE__PRIVATE_IMPLEMENTATION__HPD__SHIFT__MAX_INCL;
14842 }
14843 wuffs_base__private_implementation__high_prec_dec__small_rshift(h, n);
14844 exp2 += (int32_t)n;
14845 }
14846
14847 // Check for overflow.
14848 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
14849 goto infinity;
14850 }
14851
14852 // Extract 53 bits for the mantissa (in base-2).
14853 wuffs_base__private_implementation__high_prec_dec__small_lshift(h, 53);
14854 uint64_t man2 =
14855 wuffs_base__private_implementation__high_prec_dec__rounded_integer(h);
14856
14857 // Rounding might have added one bit. If so, shift and re-check overflow.
14858 if ((man2 >> 53) != 0) {
14859 man2 >>= 1;
14860 exp2++;
14861 if ((exp2 - f64_bias) >= 0x07FF) { // (1 << 11) - 1.
14862 goto infinity;
14863 }
14864 }
14865
14866 // Handle subnormal numbers.
14867 if ((man2 >> 52) == 0) {
14868 exp2 = f64_bias;
14869 }
14870
14871 // Pack the bits and return.
14872 uint64_t exp2_bits =
14873 (uint64_t)((exp2 - f64_bias) & 0x07FF); // (1 << 11) - 1.
14874 uint64_t bits = (man2 & 0x000FFFFFFFFFFFFF) | // (1 << 52) - 1.
14875 (exp2_bits << 52) | //
14876 (h->negative ? 0x8000000000000000 : 0); // (1 << 63).
14877
14878 wuffs_base__result_f64 ret;
14879 ret.status.repr = NULL;
14880 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14881 return ret;
14882 } while (0);
14883
14884zero:
14885 do {
14886 uint64_t bits = h->negative ? 0x8000000000000000 : 0;
14887
14888 wuffs_base__result_f64 ret;
14889 ret.status.repr = NULL;
14890 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14891 return ret;
14892 } while (0);
14893
14894infinity:
14895 do {
14896 if (options & WUFFS_BASE__PARSE_NUMBER_FXX__REJECT_INF_AND_NAN) {
14897 wuffs_base__result_f64 ret;
14898 ret.status.repr = wuffs_base__error__bad_argument;
14899 ret.value = 0;
14900 return ret;
14901 }
14902
14903 uint64_t bits = h->negative ? 0xFFF0000000000000 : 0x7FF0000000000000;
14904
14905 wuffs_base__result_f64 ret;
14906 ret.status.repr = NULL;
14907 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(bits);
14908 return ret;
14909 } while (0);
14910}
14911
14912static inline bool //
14913wuffs_base__private_implementation__is_decimal_digit(uint8_t c) {
14914 return ('0' <= c) && (c <= '9');
14915}
14916
14917WUFFS_BASE__MAYBE_STATIC wuffs_base__result_f64 //
14918wuffs_base__parse_number_f64(wuffs_base__slice_u8 s, uint32_t options) {
14919 // In practice, almost all "dd.ddddE±xxx" numbers can be represented
14920 // losslessly by a uint64_t mantissa "dddddd" and an int32_t base-10
14921 // exponent, adjusting "xxx" for the position (if present) of the decimal
14922 // separator '.' or ','.
14923 //
14924 // This (u64 man, i32 exp10) data structure is superficially similar to the
14925 // "Do It Yourself Floating Point" type from Loitsch (†), but the exponent
14926 // here is base-10, not base-2.
14927 //
14928 // If s's number fits in a (man, exp10), parse that pair with the
14929 // Eisel-Lemire algorithm. If not, or if Eisel-Lemire fails, parsing s with
14930 // the fallback algorithm is slower but comprehensive.
14931 //
14932 // † "Printing Floating-Point Numbers Quickly and Accurately with Integers"
14933 // (https://www.cs.tufts.edu/~nr/cs257/archive/florian-loitsch/printf.pdf).
14934 // Florian Loitsch is also the primary contributor to
14935 // https://github.com/google/double-conversion
14936 do {
14937 // Calculating that (man, exp10) pair needs to stay within s's bounds.
14938 // Provided that s isn't extremely long, work on a NUL-terminated copy of
14939 // s's contents. The NUL byte isn't a valid part of "±dd.ddddE±xxx".
14940 //
14941 // As the pointer p walks the contents, it's faster to repeatedly check "is
14942 // *p a valid digit" than "is p within bounds and *p a valid digit".
14943 if (s.len >= 256) {
14944 goto fallback;
14945 }
14946 uint8_t z[256];
14947 memcpy(&z[0], s.ptr, s.len);
14948 z[s.len] = 0;
14949 const uint8_t* p = &z[0];
14950
14951 // Look for a leading minus sign. Technically, we could also look for an
14952 // optional plus sign, but the "script/process-json-numbers.c with -p"
14953 // benchmark is noticably slower if we do. It's optional and, in practice,
14954 // usually absent. Let the fallback catch it.
14955 bool negative = (*p == '-');
14956 if (negative) {
14957 p++;
14958 }
14959
14960 // After walking "dd.dddd", comparing p later with p now will produce the
14961 // number of "d"s and "."s.
14962 const uint8_t* const start_of_digits_ptr = p;
14963
14964 // Walk the "d"s before a '.', 'E', NUL byte, etc. If it starts with '0',
14965 // it must be a single '0'. If it starts with a non-zero decimal digit, it
14966 // can be a sequence of decimal digits.
14967 //
14968 // Update the man variable during the walk. It's OK if man overflows now.
14969 // We'll detect that later.
14970 uint64_t man;
14971 if (*p == '0') {
14972 man = 0;
14973 p++;
14974 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14975 goto fallback;
14976 }
14977 } else if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
14978 man = ((uint8_t)(*p - '0'));
14979 p++;
14980 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
14981 man = (10 * man) + ((uint8_t)(*p - '0'));
14982 }
14983 } else {
14984 goto fallback;
14985 }
14986
14987 // Walk the "d"s after the optional decimal separator ('.' or ','),
14988 // updating the man and exp10 variables.
14989 int32_t exp10 = 0;
14990 if (*p ==
14991 ((options & WUFFS_BASE__PARSE_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
14992 ? ','
14993 : '.')) {
14994 p++;
14995 const uint8_t* first_after_separator_ptr = p;
14996 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
14997 goto fallback;
14998 }
14999 man = (10 * man) + ((uint8_t)(*p - '0'));
15000 p++;
15001 for (; wuffs_base__private_implementation__is_decimal_digit(*p); p++) {
15002 man = (10 * man) + ((uint8_t)(*p - '0'));
15003 }
15004 exp10 = ((int32_t)(first_after_separator_ptr - p));
15005 }
15006
15007 // Count the number of digits:
15008 // - for an input of "314159", digit_count is 6.
15009 // - for an input of "3.14159", digit_count is 7.
15010 //
15011 // This is off-by-one if there is a decimal separator. That's OK for now.
15012 // We'll correct for that later. The "script/process-json-numbers.c with
15013 // -p" benchmark is noticably slower if we try to correct for that now.
15014 uint32_t digit_count = (uint32_t)(p - start_of_digits_ptr);
15015
15016 // Update exp10 for the optional exponent, starting with 'E' or 'e'.
15017 if ((*p | 0x20) == 'e') {
15018 p++;
15019 int32_t exp_sign = +1;
15020 if (*p == '-') {
15021 p++;
15022 exp_sign = -1;
15023 } else if (*p == '+') {
15024 p++;
15025 }
15026 if (!wuffs_base__private_implementation__is_decimal_digit(*p)) {
15027 goto fallback;
15028 }
15029 int32_t exp_num = ((uint8_t)(*p - '0'));
15030 p++;
15031 // The rest of the exp_num walking has a peculiar control flow but, once
15032 // again, the "script/process-json-numbers.c with -p" benchmark is
15033 // sensitive to alternative formulations.
15034 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
15035 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
15036 p++;
15037 }
15038 if (wuffs_base__private_implementation__is_decimal_digit(*p)) {
15039 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
15040 p++;
15041 }
15042 while (wuffs_base__private_implementation__is_decimal_digit(*p)) {
15043 if (exp_num > 0x1000000) {
15044 goto fallback;
15045 }
15046 exp_num = (10 * exp_num) + ((uint8_t)(*p - '0'));
15047 p++;
15048 }
15049 exp10 += exp_sign * exp_num;
15050 }
15051
15052 // The Wuffs API is that the original slice has no trailing data. It also
15053 // allows underscores, which we don't catch here but the fallback should.
15054 if (p != &z[s.len]) {
15055 goto fallback;
15056 }
15057
15058 // Check that the uint64_t typed man variable has not overflowed, based on
15059 // digit_count.
15060 //
15061 // For reference:
15062 // - (1 << 63) is 9223372036854775808, which has 19 decimal digits.
15063 // - (1 << 64) is 18446744073709551616, which has 20 decimal digits.
15064 // - 19 nines, 9999999999999999999, is 0x8AC7230489E7FFFF, which has 64
15065 // bits and 16 hexadecimal digits.
15066 // - 20 nines, 99999999999999999999, is 0x56BC75E2D630FFFFF, which has 67
15067 // bits and 17 hexadecimal digits.
15068 if (digit_count > 19) {
15069 // Even if we have more than 19 pseudo-digits, it's not yet definitely an
15070 // overflow. Recall that digit_count might be off-by-one (too large) if
15071 // there's a decimal separator. It will also over-report the number of
15072 // meaningful digits if the input looks something like "0.000dddExxx".
15073 //
15074 // We adjust by the number of leading '0's and '.'s and re-compare to 19.
15075 // Once again, technically, we could skip ','s too, but that perturbs the
15076 // "script/process-json-numbers.c with -p" benchmark.
15077 const uint8_t* q = start_of_digits_ptr;
15078 for (; (*q == '0') || (*q == '.'); q++) {
15079 }
15080 digit_count -= (uint32_t)(q - start_of_digits_ptr);
15081 if (digit_count > 19) {
15082 goto fallback;
15083 }
15084 }
15085
15086 // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
15087 // preconditions include that exp10 is in the range [-307 ..= 288].
15088 if ((exp10 < -307) || (288 < exp10)) {
15089 goto fallback;
15090 }
15091
15092 // If both man and (10 ** exp10) are exactly representable by a double, we
15093 // don't need to run the Eisel-Lemire algorithm.
15094 if ((-22 <= exp10) && (exp10 <= 22) && ((man >> 53) == 0)) {
15095 double d = (double)man;
15096 if (exp10 >= 0) {
15097 d *= wuffs_base__private_implementation__f64_powers_of_10[+exp10];
15098 } else {
15099 d /= wuffs_base__private_implementation__f64_powers_of_10[-exp10];
15100 }
15101 wuffs_base__result_f64 ret;
15102 ret.status.repr = NULL;
15103 ret.value = negative ? -d : +d;
15104 return ret;
15105 }
15106
15107 // The wuffs_base__private_implementation__parse_number_f64_eisel_lemire
15108 // preconditions include that man is non-zero. Parsing "0" should be caught
15109 // by the "If both man and (10 ** exp10)" above, but "0e99" might not.
15110 if (man == 0) {
15111 goto fallback;
15112 }
15113
15114 // Our man and exp10 are in range. Run the Eisel-Lemire algorithm.
15115 int64_t r =
15116 wuffs_base__private_implementation__parse_number_f64_eisel_lemire(
15117 man, exp10);
15118 if (r < 0) {
15119 goto fallback;
15120 }
15121 wuffs_base__result_f64 ret;
15122 ret.status.repr = NULL;
15123 ret.value = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
15124 ((uint64_t)r) | (((uint64_t)negative) << 63));
15125 return ret;
15126 } while (0);
15127
15128fallback:
15129 do {
15130 wuffs_base__private_implementation__high_prec_dec h;
15131 wuffs_base__status status =
15132 wuffs_base__private_implementation__high_prec_dec__parse(&h, s,
15133 options);
15134 if (status.repr) {
15135 return wuffs_base__private_implementation__parse_number_f64_special(
15136 s, options);
15137 }
15138 return wuffs_base__private_implementation__high_prec_dec__to_f64(&h,
15139 options);
15140 } while (0);
15141}
15142
15143// --------
15144
15145static inline size_t //
15146wuffs_base__private_implementation__render_inf(wuffs_base__slice_u8 dst,
15147 bool neg,
15148 uint32_t options) {
15149 if (neg) {
15150 if (dst.len < 4) {
15151 return 0;
15152 }
15153 wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492D); // '-Inf'le.
15154 return 4;
15155 }
15156
15157 if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
15158 if (dst.len < 4) {
15159 return 0;
15160 }
15161 wuffs_base__poke_u32le__no_bounds_check(dst.ptr, 0x666E492B); // '+Inf'le.
15162 return 4;
15163 }
15164
15165 if (dst.len < 3) {
15166 return 0;
15167 }
15168 wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x666E49); // 'Inf'le.
15169 return 3;
15170}
15171
15172static inline size_t //
15173wuffs_base__private_implementation__render_nan(wuffs_base__slice_u8 dst) {
15174 if (dst.len < 3) {
15175 return 0;
15176 }
15177 wuffs_base__poke_u24le__no_bounds_check(dst.ptr, 0x4E614E); // 'NaN'le.
15178 return 3;
15179}
15180
15181static size_t //
15182wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
15183 wuffs_base__slice_u8 dst,
15184 wuffs_base__private_implementation__high_prec_dec* h,
15185 uint32_t precision,
15186 uint32_t options) {
15187 size_t n = (h->negative ||
15188 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
15189 ? 1
15190 : 0;
15191 if (h->decimal_point <= 0) {
15192 n += 1;
15193 } else {
15194 n += (size_t)(h->decimal_point);
15195 }
15196 if (precision > 0) {
15197 n += precision + 1; // +1 for the '.'.
15198 }
15199
15200 // Don't modify dst if the formatted number won't fit.
15201 if (n > dst.len) {
15202 return 0;
15203 }
15204
15205 // Align-left or align-right.
15206 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
15207 ? &dst.ptr[dst.len - n]
15208 : &dst.ptr[0];
15209
15210 // Leading "±".
15211 if (h->negative) {
15212 *ptr++ = '-';
15213 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
15214 *ptr++ = '+';
15215 }
15216
15217 // Integral digits.
15218 if (h->decimal_point <= 0) {
15219 *ptr++ = '0';
15220 } else {
15221 uint32_t m =
15222 wuffs_base__u32__min(h->num_digits, (uint32_t)(h->decimal_point));
15223 uint32_t i = 0;
15224 for (; i < m; i++) {
15225 *ptr++ = (uint8_t)('0' | h->digits[i]);
15226 }
15227 for (; i < (uint32_t)(h->decimal_point); i++) {
15228 *ptr++ = '0';
15229 }
15230 }
15231
15232 // Separator and then fractional digits.
15233 if (precision > 0) {
15234 *ptr++ =
15235 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
15236 ? ','
15237 : '.';
15238 uint32_t i = 0;
15239 for (; i < precision; i++) {
15240 uint32_t j = ((uint32_t)(h->decimal_point)) + i;
15241 *ptr++ = (uint8_t)('0' | ((j < h->num_digits) ? h->digits[j] : 0));
15242 }
15243 }
15244
15245 return n;
15246}
15247
15248static size_t //
15249wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
15250 wuffs_base__slice_u8 dst,
15251 wuffs_base__private_implementation__high_prec_dec* h,
15252 uint32_t precision,
15253 uint32_t options) {
15254 int32_t exp = 0;
15255 if (h->num_digits > 0) {
15256 exp = h->decimal_point - 1;
15257 }
15258 bool negative_exp = exp < 0;
15259 if (negative_exp) {
15260 exp = -exp;
15261 }
15262
15263 size_t n = (h->negative ||
15264 (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN))
15265 ? 4
15266 : 3; // Mininum 3 bytes: first digit and then "e±".
15267 if (precision > 0) {
15268 n += precision + 1; // +1 for the '.'.
15269 }
15270 n += (exp < 100) ? 2 : 3;
15271
15272 // Don't modify dst if the formatted number won't fit.
15273 if (n > dst.len) {
15274 return 0;
15275 }
15276
15277 // Align-left or align-right.
15278 uint8_t* ptr = (options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
15279 ? &dst.ptr[dst.len - n]
15280 : &dst.ptr[0];
15281
15282 // Leading "±".
15283 if (h->negative) {
15284 *ptr++ = '-';
15285 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
15286 *ptr++ = '+';
15287 }
15288
15289 // Integral digit.
15290 if (h->num_digits > 0) {
15291 *ptr++ = (uint8_t)('0' | h->digits[0]);
15292 } else {
15293 *ptr++ = '0';
15294 }
15295
15296 // Separator and then fractional digits.
15297 if (precision > 0) {
15298 *ptr++ =
15299 (options & WUFFS_BASE__RENDER_NUMBER_FXX__DECIMAL_SEPARATOR_IS_A_COMMA)
15300 ? ','
15301 : '.';
15302 uint32_t i = 1;
15303 uint32_t j = wuffs_base__u32__min(h->num_digits, precision + 1);
15304 for (; i < j; i++) {
15305 *ptr++ = (uint8_t)('0' | h->digits[i]);
15306 }
15307 for (; i <= precision; i++) {
15308 *ptr++ = '0';
15309 }
15310 }
15311
15312 // Exponent: "e±" and then 2 or 3 digits.
15313 *ptr++ = 'e';
15314 *ptr++ = negative_exp ? '-' : '+';
15315 if (exp < 10) {
15316 *ptr++ = '0';
15317 *ptr++ = (uint8_t)('0' | exp);
15318 } else if (exp < 100) {
15319 *ptr++ = (uint8_t)('0' | (exp / 10));
15320 *ptr++ = (uint8_t)('0' | (exp % 10));
15321 } else {
15322 int32_t e = exp / 100;
15323 exp -= e * 100;
15324 *ptr++ = (uint8_t)('0' | e);
15325 *ptr++ = (uint8_t)('0' | (exp / 10));
15326 *ptr++ = (uint8_t)('0' | (exp % 10));
15327 }
15328
15329 return n;
15330}
15331
15332WUFFS_BASE__MAYBE_STATIC size_t //
15333wuffs_base__render_number_f64(wuffs_base__slice_u8 dst,
15334 double x,
15335 uint32_t precision,
15336 uint32_t options) {
15337 // Decompose x (64 bits) into negativity (1 bit), base-2 exponent (11 bits
15338 // with a -1023 bias) and mantissa (52 bits).
15339 uint64_t bits = wuffs_base__ieee_754_bit_representation__from_f64_to_u64(x);
15340 bool neg = (bits >> 63) != 0;
15341 int32_t exp2 = ((int32_t)(bits >> 52)) & 0x7FF;
15342 uint64_t man = bits & 0x000FFFFFFFFFFFFFul;
15343
15344 // Apply the exponent bias and set the implicit top bit of the mantissa,
15345 // unless x is subnormal. Also take care of Inf and NaN.
15346 if (exp2 == 0x7FF) {
15347 if (man != 0) {
15348 return wuffs_base__private_implementation__render_nan(dst);
15349 }
15350 return wuffs_base__private_implementation__render_inf(dst, neg, options);
15351 } else if (exp2 == 0) {
15352 exp2 = -1022;
15353 } else {
15354 exp2 -= 1023;
15355 man |= 0x0010000000000000ul;
15356 }
15357
15358 // Ensure that precision isn't too large.
15359 if (precision > 4095) {
15360 precision = 4095;
15361 }
15362
15363 // Convert from the (neg, exp2, man) tuple to an HPD.
15364 wuffs_base__private_implementation__high_prec_dec h;
15365 wuffs_base__private_implementation__high_prec_dec__assign(&h, man, neg);
15366 if (h.num_digits > 0) {
15367 wuffs_base__private_implementation__high_prec_dec__lshift(
15368 &h, exp2 - 52); // 52 mantissa bits.
15369 }
15370
15371 // Handle the "%e" and "%f" formats.
15372 switch (options & (WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT |
15373 WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT)) {
15374 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_ABSENT: // The "%"f" format.
15375 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
15376 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
15377 &h, exp2, man);
15378 int32_t p = ((int32_t)(h.num_digits)) - h.decimal_point;
15379 precision = ((uint32_t)(wuffs_base__i32__max(0, p)));
15380 } else {
15381 wuffs_base__private_implementation__high_prec_dec__round_nearest(
15382 &h, ((int32_t)precision) + h.decimal_point);
15383 }
15384 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
15385 dst, &h, precision, options);
15386
15387 case WUFFS_BASE__RENDER_NUMBER_FXX__EXPONENT_PRESENT: // The "%e" format.
15388 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
15389 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
15390 &h, exp2, man);
15391 precision = (h.num_digits > 0) ? (h.num_digits - 1) : 0;
15392 } else {
15393 wuffs_base__private_implementation__high_prec_dec__round_nearest(
15394 &h, ((int32_t)precision) + 1);
15395 }
15396 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
15397 dst, &h, precision, options);
15398 }
15399
15400 // We have the "%g" format and so precision means the number of significant
15401 // digits, not the number of digits after the decimal separator. Perform
15402 // rounding and determine whether to use "%e" or "%f".
15403 int32_t e_threshold = 0;
15404 if (options & WUFFS_BASE__RENDER_NUMBER_FXX__JUST_ENOUGH_PRECISION) {
15405 wuffs_base__private_implementation__high_prec_dec__round_just_enough(
15406 &h, exp2, man);
15407 precision = h.num_digits;
15408 e_threshold = 6;
15409 } else {
15410 if (precision == 0) {
15411 precision = 1;
15412 }
15413 wuffs_base__private_implementation__high_prec_dec__round_nearest(
15414 &h, ((int32_t)precision));
15415 e_threshold = ((int32_t)precision);
15416 int32_t nd = ((int32_t)(h.num_digits));
15417 if ((e_threshold > nd) && (nd >= h.decimal_point)) {
15418 e_threshold = nd;
15419 }
15420 }
15421
15422 // Use the "%e" format if the exponent is large.
15423 int32_t e = h.decimal_point - 1;
15424 if ((e < -4) || (e_threshold <= e)) {
15425 uint32_t p = wuffs_base__u32__min(precision, h.num_digits);
15426 return wuffs_base__private_implementation__high_prec_dec__render_exponent_present(
15427 dst, &h, (p > 0) ? (p - 1) : 0, options);
15428 }
15429
15430 // Use the "%f" format otherwise.
15431 int32_t p = ((int32_t)precision);
15432 if (p > h.decimal_point) {
15433 p = ((int32_t)(h.num_digits));
15434 }
15435 precision = ((uint32_t)(wuffs_base__i32__max(0, p - h.decimal_point)));
15436 return wuffs_base__private_implementation__high_prec_dec__render_exponent_absent(
15437 dst, &h, precision, options);
15438}
15439
15440#endif // !defined(WUFFS_CONFIG__MODULES) ||
15441 // defined(WUFFS_CONFIG__MODULE__BASE) ||
15442 // defined(WUFFS_CONFIG__MODULE__BASE__FLOATCONV)
15443
15444#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
15445 defined(WUFFS_CONFIG__MODULE__BASE__INTCONV)
15446
15447// ---------------- Integer
15448
15449// wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits,
15450// and (0x80 | v) for valid digits, where v is the 4 bit value.
15451
15452static const uint8_t wuffs_base__parse_number__decimal_digits[256] = {
15453 // 0 1 2 3 4 5 6 7
15454 // 8 9 A B C D E F
15455 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
15456 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
15457 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
15458 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
15459 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
15460 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
15461 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'.
15462 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'.
15463
15464 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47.
15465 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
15466 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
15467 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
15468 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67.
15469 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
15470 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
15471 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
15472
15473 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87.
15474 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F.
15475 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97.
15476 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F.
15477 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7.
15478 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF.
15479 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7.
15480 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF.
15481
15482 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7.
15483 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF.
15484 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7.
15485 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF.
15486 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7.
15487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF.
15488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7.
15489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF.
15490 // 0 1 2 3 4 5 6 7
15491 // 8 9 A B C D E F
15492};
15493
15494static const uint8_t wuffs_base__parse_number__hexadecimal_digits[256] = {
15495 // 0 1 2 3 4 5 6 7
15496 // 8 9 A B C D E F
15497 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
15498 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
15499 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
15500 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
15501 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
15502 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
15503 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, // 0x30 ..= 0x37. '0'-'7'.
15504 0x88, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F. '8'-'9'.
15505
15506 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x40 ..= 0x47. 'A'-'F'.
15507 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
15508 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
15509 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
15510 0x00, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x00, // 0x60 ..= 0x67. 'a'-'f'.
15511 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
15512 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
15513 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
15514
15515 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x80 ..= 0x87.
15516 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x88 ..= 0x8F.
15517 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x90 ..= 0x97.
15518 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x98 ..= 0x9F.
15519 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA0 ..= 0xA7.
15520 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xA8 ..= 0xAF.
15521 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB0 ..= 0xB7.
15522 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xB8 ..= 0xBF.
15523
15524 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC0 ..= 0xC7.
15525 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xC8 ..= 0xCF.
15526 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD0 ..= 0xD7.
15527 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xD8 ..= 0xDF.
15528 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE0 ..= 0xE7.
15529 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xE8 ..= 0xEF.
15530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF0 ..= 0xF7.
15531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0xF8 ..= 0xFF.
15532 // 0 1 2 3 4 5 6 7
15533 // 8 9 A B C D E F
15534};
15535
15536static const uint8_t wuffs_base__private_implementation__encode_base16[16] = {
15537 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 0x00 ..= 0x07.
15538 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 0x08 ..= 0x0F.
15539};
15540
15541// --------
15542
15543WUFFS_BASE__MAYBE_STATIC wuffs_base__result_i64 //
15544wuffs_base__parse_number_i64(wuffs_base__slice_u8 s, uint32_t options) {
15545 uint8_t* p = s.ptr;
15546 uint8_t* q = s.ptr + s.len;
15547
15548 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
15549 for (; (p < q) && (*p == '_'); p++) {
15550 }
15551 }
15552
15553 bool negative = false;
15554 if (p >= q) {
15555 goto fail_bad_argument;
15556 } else if (*p == '-') {
15557 p++;
15558 negative = true;
15559 } else if (*p == '+') {
15560 p++;
15561 }
15562
15563 do {
15564 wuffs_base__result_u64 r = wuffs_base__parse_number_u64(
15565 wuffs_base__make_slice_u8(p, (size_t)(q - p)), options);
15566 if (r.status.repr != NULL) {
15567 wuffs_base__result_i64 ret;
15568 ret.status.repr = r.status.repr;
15569 ret.value = 0;
15570 return ret;
15571 } else if (negative) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100015572 if (r.value < 0x8000000000000000) {
15573 wuffs_base__result_i64 ret;
15574 ret.status.repr = NULL;
15575 ret.value = -(int64_t)(r.value);
15576 return ret;
15577 } else if (r.value == 0x8000000000000000) {
15578 wuffs_base__result_i64 ret;
15579 ret.status.repr = NULL;
15580 ret.value = INT64_MIN;
15581 return ret;
Nigel Taoe360a532021-04-05 22:47:03 +100015582 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100015583 goto fail_out_of_bounds;
Nigel Taoe360a532021-04-05 22:47:03 +100015584 } else if (r.value > 0x7FFFFFFFFFFFFFFF) {
15585 goto fail_out_of_bounds;
15586 } else {
15587 wuffs_base__result_i64 ret;
15588 ret.status.repr = NULL;
15589 ret.value = +(int64_t)(r.value);
15590 return ret;
15591 }
15592 } while (0);
15593
15594fail_bad_argument:
15595 do {
15596 wuffs_base__result_i64 ret;
15597 ret.status.repr = wuffs_base__error__bad_argument;
15598 ret.value = 0;
15599 return ret;
15600 } while (0);
15601
15602fail_out_of_bounds:
15603 do {
15604 wuffs_base__result_i64 ret;
15605 ret.status.repr = wuffs_base__error__out_of_bounds;
15606 ret.value = 0;
15607 return ret;
15608 } while (0);
15609}
15610
15611WUFFS_BASE__MAYBE_STATIC wuffs_base__result_u64 //
15612wuffs_base__parse_number_u64(wuffs_base__slice_u8 s, uint32_t options) {
15613 uint8_t* p = s.ptr;
15614 uint8_t* q = s.ptr + s.len;
15615
15616 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
15617 for (; (p < q) && (*p == '_'); p++) {
15618 }
15619 }
15620
15621 if (p >= q) {
15622 goto fail_bad_argument;
15623
15624 } else if (*p == '0') {
15625 p++;
15626 if (p >= q) {
15627 goto ok_zero;
15628 }
15629 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
15630 if (*p == '_') {
15631 p++;
15632 for (; p < q; p++) {
15633 if (*p != '_') {
15634 if (options &
15635 WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) {
15636 goto decimal;
15637 }
15638 goto fail_bad_argument;
15639 }
15640 }
15641 goto ok_zero;
15642 }
15643 }
15644
15645 if ((*p == 'x') || (*p == 'X')) {
15646 p++;
15647 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
15648 for (; (p < q) && (*p == '_'); p++) {
15649 }
15650 }
15651 if (p < q) {
15652 goto hexadecimal;
15653 }
15654
15655 } else if ((*p == 'd') || (*p == 'D')) {
15656 p++;
15657 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES) {
15658 for (; (p < q) && (*p == '_'); p++) {
15659 }
15660 }
15661 if (p < q) {
15662 goto decimal;
15663 }
15664 }
15665
15666 if (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_MULTIPLE_LEADING_ZEROES) {
15667 goto decimal;
15668 }
15669 goto fail_bad_argument;
15670 }
15671
15672decimal:
15673 do {
15674 uint64_t v = wuffs_base__parse_number__decimal_digits[*p++];
15675 if (v == 0) {
15676 goto fail_bad_argument;
15677 }
15678 v &= 0x0F;
15679
15680 // UINT64_MAX is 18446744073709551615, which is ((10 * max10) + max1).
15681 const uint64_t max10 = 1844674407370955161u;
15682 const uint8_t max1 = 5;
15683
15684 for (; p < q; p++) {
15685 if ((*p == '_') &&
15686 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
15687 continue;
15688 }
15689 uint8_t digit = wuffs_base__parse_number__decimal_digits[*p];
15690 if (digit == 0) {
15691 goto fail_bad_argument;
15692 }
15693 digit &= 0x0F;
15694 if ((v > max10) || ((v == max10) && (digit > max1))) {
15695 goto fail_out_of_bounds;
15696 }
15697 v = (10 * v) + ((uint64_t)(digit));
15698 }
15699
15700 wuffs_base__result_u64 ret;
15701 ret.status.repr = NULL;
15702 ret.value = v;
15703 return ret;
15704 } while (0);
15705
15706hexadecimal:
15707 do {
15708 uint64_t v = wuffs_base__parse_number__hexadecimal_digits[*p++];
15709 if (v == 0) {
15710 goto fail_bad_argument;
15711 }
15712 v &= 0x0F;
15713
15714 for (; p < q; p++) {
15715 if ((*p == '_') &&
15716 (options & WUFFS_BASE__PARSE_NUMBER_XXX__ALLOW_UNDERSCORES)) {
15717 continue;
15718 }
15719 uint8_t digit = wuffs_base__parse_number__hexadecimal_digits[*p];
15720 if (digit == 0) {
15721 goto fail_bad_argument;
15722 }
15723 digit &= 0x0F;
15724 if ((v >> 60) != 0) {
15725 goto fail_out_of_bounds;
15726 }
15727 v = (v << 4) | ((uint64_t)(digit));
15728 }
15729
15730 wuffs_base__result_u64 ret;
15731 ret.status.repr = NULL;
15732 ret.value = v;
15733 return ret;
15734 } while (0);
15735
15736ok_zero:
15737 do {
15738 wuffs_base__result_u64 ret;
15739 ret.status.repr = NULL;
15740 ret.value = 0;
15741 return ret;
15742 } while (0);
15743
15744fail_bad_argument:
15745 do {
15746 wuffs_base__result_u64 ret;
15747 ret.status.repr = wuffs_base__error__bad_argument;
15748 ret.value = 0;
15749 return ret;
15750 } while (0);
15751
15752fail_out_of_bounds:
15753 do {
15754 wuffs_base__result_u64 ret;
15755 ret.status.repr = wuffs_base__error__out_of_bounds;
15756 ret.value = 0;
15757 return ret;
15758 } while (0);
15759}
15760
15761// --------
15762
15763// wuffs_base__render_number__first_hundred contains the decimal encodings of
15764// the first one hundred numbers [0 ..= 99].
15765static const uint8_t wuffs_base__render_number__first_hundred[200] = {
15766 '0', '0', '0', '1', '0', '2', '0', '3', '0', '4', //
15767 '0', '5', '0', '6', '0', '7', '0', '8', '0', '9', //
15768 '1', '0', '1', '1', '1', '2', '1', '3', '1', '4', //
15769 '1', '5', '1', '6', '1', '7', '1', '8', '1', '9', //
15770 '2', '0', '2', '1', '2', '2', '2', '3', '2', '4', //
15771 '2', '5', '2', '6', '2', '7', '2', '8', '2', '9', //
15772 '3', '0', '3', '1', '3', '2', '3', '3', '3', '4', //
15773 '3', '5', '3', '6', '3', '7', '3', '8', '3', '9', //
15774 '4', '0', '4', '1', '4', '2', '4', '3', '4', '4', //
15775 '4', '5', '4', '6', '4', '7', '4', '8', '4', '9', //
15776 '5', '0', '5', '1', '5', '2', '5', '3', '5', '4', //
15777 '5', '5', '5', '6', '5', '7', '5', '8', '5', '9', //
15778 '6', '0', '6', '1', '6', '2', '6', '3', '6', '4', //
15779 '6', '5', '6', '6', '6', '7', '6', '8', '6', '9', //
15780 '7', '0', '7', '1', '7', '2', '7', '3', '7', '4', //
15781 '7', '5', '7', '6', '7', '7', '7', '8', '7', '9', //
15782 '8', '0', '8', '1', '8', '2', '8', '3', '8', '4', //
15783 '8', '5', '8', '6', '8', '7', '8', '8', '8', '9', //
15784 '9', '0', '9', '1', '9', '2', '9', '3', '9', '4', //
15785 '9', '5', '9', '6', '9', '7', '9', '8', '9', '9', //
15786};
15787
15788static size_t //
15789wuffs_base__private_implementation__render_number_u64(wuffs_base__slice_u8 dst,
15790 uint64_t x,
15791 uint32_t options,
15792 bool neg) {
15793 uint8_t buf[WUFFS_BASE__U64__BYTE_LENGTH__MAX_INCL];
15794 uint8_t* ptr = &buf[0] + sizeof(buf);
15795
15796 while (x >= 100) {
15797 size_t index = ((size_t)((x % 100) * 2));
15798 x /= 100;
15799 uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0];
15800 uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1];
15801 ptr -= 2;
15802 ptr[0] = s0;
15803 ptr[1] = s1;
15804 }
15805
15806 if (x < 10) {
15807 ptr -= 1;
15808 ptr[0] = (uint8_t)('0' + x);
15809 } else {
15810 size_t index = ((size_t)(x * 2));
15811 uint8_t s0 = wuffs_base__render_number__first_hundred[index + 0];
15812 uint8_t s1 = wuffs_base__render_number__first_hundred[index + 1];
15813 ptr -= 2;
15814 ptr[0] = s0;
15815 ptr[1] = s1;
15816 }
15817
15818 if (neg) {
15819 ptr -= 1;
15820 ptr[0] = '-';
15821 } else if (options & WUFFS_BASE__RENDER_NUMBER_XXX__LEADING_PLUS_SIGN) {
15822 ptr -= 1;
15823 ptr[0] = '+';
15824 }
15825
15826 size_t n = sizeof(buf) - ((size_t)(ptr - &buf[0]));
15827 if (n > dst.len) {
15828 return 0;
15829 }
15830 memcpy(dst.ptr + ((options & WUFFS_BASE__RENDER_NUMBER_XXX__ALIGN_RIGHT)
15831 ? (dst.len - n)
15832 : 0),
15833 ptr, n);
15834 return n;
15835}
15836
15837WUFFS_BASE__MAYBE_STATIC size_t //
15838wuffs_base__render_number_i64(wuffs_base__slice_u8 dst,
15839 int64_t x,
15840 uint32_t options) {
15841 uint64_t u = (uint64_t)x;
15842 bool neg = x < 0;
15843 if (neg) {
15844 u = 1 + ~u;
15845 }
15846 return wuffs_base__private_implementation__render_number_u64(dst, u, options,
15847 neg);
15848}
15849
15850WUFFS_BASE__MAYBE_STATIC size_t //
15851wuffs_base__render_number_u64(wuffs_base__slice_u8 dst,
15852 uint64_t x,
15853 uint32_t options) {
15854 return wuffs_base__private_implementation__render_number_u64(dst, x, options,
15855 false);
15856}
15857
15858// ---------------- Base-16
15859
15860WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15861wuffs_base__base_16__decode2(wuffs_base__slice_u8 dst,
15862 wuffs_base__slice_u8 src,
15863 bool src_closed,
15864 uint32_t options) {
15865 wuffs_base__transform__output o;
15866 size_t src_len2 = src.len / 2;
15867 size_t len;
15868 if (dst.len < src_len2) {
15869 len = dst.len;
15870 o.status.repr = wuffs_base__suspension__short_write;
15871 } else {
15872 len = src_len2;
15873 if (!src_closed) {
15874 o.status.repr = wuffs_base__suspension__short_read;
15875 } else if (src.len & 1) {
15876 o.status.repr = wuffs_base__error__bad_data;
15877 } else {
15878 o.status.repr = NULL;
15879 }
15880 }
15881
15882 uint8_t* d = dst.ptr;
15883 uint8_t* s = src.ptr;
15884 size_t n = len;
15885
15886 while (n--) {
15887 *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[0]] << 4) |
15888 (wuffs_base__parse_number__hexadecimal_digits[s[1]] & 0x0F));
15889 d += 1;
15890 s += 2;
15891 }
15892
15893 o.num_dst = len;
15894 o.num_src = len * 2;
15895 return o;
15896}
15897
15898WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15899wuffs_base__base_16__decode4(wuffs_base__slice_u8 dst,
15900 wuffs_base__slice_u8 src,
15901 bool src_closed,
15902 uint32_t options) {
15903 wuffs_base__transform__output o;
15904 size_t src_len4 = src.len / 4;
15905 size_t len = dst.len < src_len4 ? dst.len : src_len4;
15906 if (dst.len < src_len4) {
15907 len = dst.len;
15908 o.status.repr = wuffs_base__suspension__short_write;
15909 } else {
15910 len = src_len4;
15911 if (!src_closed) {
15912 o.status.repr = wuffs_base__suspension__short_read;
15913 } else if (src.len & 1) {
15914 o.status.repr = wuffs_base__error__bad_data;
15915 } else {
15916 o.status.repr = NULL;
15917 }
15918 }
15919
15920 uint8_t* d = dst.ptr;
15921 uint8_t* s = src.ptr;
15922 size_t n = len;
15923
15924 while (n--) {
15925 *d = (uint8_t)((wuffs_base__parse_number__hexadecimal_digits[s[2]] << 4) |
15926 (wuffs_base__parse_number__hexadecimal_digits[s[3]] & 0x0F));
15927 d += 1;
15928 s += 4;
15929 }
15930
15931 o.num_dst = len;
15932 o.num_src = len * 4;
15933 return o;
15934}
15935
15936WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15937wuffs_base__base_16__encode2(wuffs_base__slice_u8 dst,
15938 wuffs_base__slice_u8 src,
15939 bool src_closed,
15940 uint32_t options) {
15941 wuffs_base__transform__output o;
15942 size_t dst_len2 = dst.len / 2;
15943 size_t len;
15944 if (dst_len2 < src.len) {
15945 len = dst_len2;
15946 o.status.repr = wuffs_base__suspension__short_write;
15947 } else {
15948 len = src.len;
15949 if (!src_closed) {
15950 o.status.repr = wuffs_base__suspension__short_read;
15951 } else {
15952 o.status.repr = NULL;
15953 }
15954 }
15955
15956 uint8_t* d = dst.ptr;
15957 uint8_t* s = src.ptr;
15958 size_t n = len;
15959
15960 while (n--) {
15961 uint8_t c = *s;
15962 d[0] = wuffs_base__private_implementation__encode_base16[c >> 4];
15963 d[1] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
15964 d += 2;
15965 s += 1;
15966 }
15967
15968 o.num_dst = len * 2;
15969 o.num_src = len;
15970 return o;
15971}
15972
15973WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
15974wuffs_base__base_16__encode4(wuffs_base__slice_u8 dst,
15975 wuffs_base__slice_u8 src,
15976 bool src_closed,
15977 uint32_t options) {
15978 wuffs_base__transform__output o;
15979 size_t dst_len4 = dst.len / 4;
15980 size_t len;
15981 if (dst_len4 < src.len) {
15982 len = dst_len4;
15983 o.status.repr = wuffs_base__suspension__short_write;
15984 } else {
15985 len = src.len;
15986 if (!src_closed) {
15987 o.status.repr = wuffs_base__suspension__short_read;
15988 } else {
15989 o.status.repr = NULL;
15990 }
15991 }
15992
15993 uint8_t* d = dst.ptr;
15994 uint8_t* s = src.ptr;
15995 size_t n = len;
15996
15997 while (n--) {
15998 uint8_t c = *s;
15999 d[0] = '\\';
16000 d[1] = 'x';
16001 d[2] = wuffs_base__private_implementation__encode_base16[c >> 4];
16002 d[3] = wuffs_base__private_implementation__encode_base16[c & 0x0F];
16003 d += 4;
16004 s += 1;
16005 }
16006
16007 o.num_dst = len * 4;
16008 o.num_src = len;
16009 return o;
16010}
16011
16012// ---------------- Base-64
16013
16014// The two base-64 alphabets, std and url, differ only in the last two codes.
16015// - std: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
16016// - url: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
16017
16018static const uint8_t wuffs_base__base_64__decode_std[256] = {
16019 // 0 1 2 3 4 5 6 7
16020 // 8 9 A B C D E F
16021 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07.
16022 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F.
16023 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17.
16024 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F.
16025 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27.
16026 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, 0x80, 0x3F, // 0x28 ..= 0x2F.
16027 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37.
16028 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F.
16029
16030 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47.
16031 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F.
16032 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57.
16033 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x58 ..= 0x5F.
16034 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67.
16035 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F.
16036 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77.
16037 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F.
16038
16039 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87.
16040 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F.
16041 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97.
16042 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F.
16043 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7.
16044 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF.
16045 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7.
16046 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF.
16047
16048 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7.
16049 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF.
16050 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7.
16051 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF.
16052 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7.
16053 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF.
16054 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
16055 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
16056 // 0 1 2 3 4 5 6 7
16057 // 8 9 A B C D E F
16058};
16059
16060static const uint8_t wuffs_base__base_64__decode_url[256] = {
16061 // 0 1 2 3 4 5 6 7
16062 // 8 9 A B C D E F
16063 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x00 ..= 0x07.
16064 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x08 ..= 0x0F.
16065 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x10 ..= 0x17.
16066 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x18 ..= 0x1F.
16067 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x20 ..= 0x27.
16068 0x80, 0x80, 0x80, 0x80, 0x80, 0x3E, 0x80, 0x80, // 0x28 ..= 0x2F.
16069 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, // 0x30 ..= 0x37.
16070 0x3C, 0x3D, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x38 ..= 0x3F.
16071
16072 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // 0x40 ..= 0x47.
16073 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, // 0x48 ..= 0x4F.
16074 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, // 0x50 ..= 0x57.
16075 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x3F, // 0x58 ..= 0x5F.
16076 0x80, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, // 0x60 ..= 0x67.
16077 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, // 0x68 ..= 0x6F.
16078 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, // 0x70 ..= 0x77.
16079 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x78 ..= 0x7F.
16080
16081 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x80 ..= 0x87.
16082 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x88 ..= 0x8F.
16083 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x90 ..= 0x97.
16084 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0x98 ..= 0x9F.
16085 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA0 ..= 0xA7.
16086 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xA8 ..= 0xAF.
16087 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB0 ..= 0xB7.
16088 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xB8 ..= 0xBF.
16089
16090 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC0 ..= 0xC7.
16091 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xC8 ..= 0xCF.
16092 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD0 ..= 0xD7.
16093 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xD8 ..= 0xDF.
16094 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE0 ..= 0xE7.
16095 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xE8 ..= 0xEF.
16096 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
16097 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
16098 // 0 1 2 3 4 5 6 7
16099 // 8 9 A B C D E F
16100};
16101
16102static const uint8_t wuffs_base__base_64__encode_std[64] = {
16103 // 0 1 2 3 4 5 6 7
16104 // 8 9 A B C D E F
16105 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07.
16106 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F.
16107 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17.
16108 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F.
16109 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27.
16110 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F.
16111 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37.
16112 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2B, 0x2F, // 0x38 ..= 0x3F.
16113};
16114
16115static const uint8_t wuffs_base__base_64__encode_url[64] = {
16116 // 0 1 2 3 4 5 6 7
16117 // 8 9 A B C D E F
16118 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, // 0x00 ..= 0x07.
16119 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, // 0x08 ..= 0x0F.
16120 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, // 0x10 ..= 0x17.
16121 0x59, 0x5A, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 0x18 ..= 0x1F.
16122 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, // 0x20 ..= 0x27.
16123 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, // 0x28 ..= 0x2F.
16124 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, // 0x30 ..= 0x37.
16125 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x2D, 0x5F, // 0x38 ..= 0x3F.
16126};
16127
16128// --------
16129
16130WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
16131wuffs_base__base_64__decode(wuffs_base__slice_u8 dst,
16132 wuffs_base__slice_u8 src,
16133 bool src_closed,
16134 uint32_t options) {
16135 const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET)
16136 ? wuffs_base__base_64__decode_url
16137 : wuffs_base__base_64__decode_std;
16138 wuffs_base__transform__output o;
16139 uint8_t* d_ptr = dst.ptr;
16140 size_t d_len = dst.len;
16141 const uint8_t* s_ptr = src.ptr;
16142 size_t s_len = src.len;
16143 bool pad = false;
16144
16145 while (s_len >= 4) {
16146 uint32_t s = wuffs_base__peek_u32le__no_bounds_check(s_ptr);
16147 uint32_t s0 = alphabet[0xFF & (s >> 0)];
16148 uint32_t s1 = alphabet[0xFF & (s >> 8)];
16149 uint32_t s2 = alphabet[0xFF & (s >> 16)];
16150 uint32_t s3 = alphabet[0xFF & (s >> 24)];
16151
16152 if (((s0 | s1 | s2 | s3) & 0xC0) != 0) {
16153 if (s_len > 4) {
16154 o.status.repr = wuffs_base__error__bad_data;
16155 goto done;
16156 } else if (!src_closed) {
16157 o.status.repr = wuffs_base__suspension__short_read;
16158 goto done;
16159 } else if ((options & WUFFS_BASE__BASE_64__DECODE_ALLOW_PADDING) &&
16160 (s_ptr[3] == '=')) {
16161 pad = true;
16162 if (s_ptr[2] == '=') {
16163 goto src2;
16164 }
16165 goto src3;
16166 }
16167 o.status.repr = wuffs_base__error__bad_data;
16168 goto done;
16169 }
16170
16171 if (d_len < 3) {
16172 o.status.repr = wuffs_base__suspension__short_write;
16173 goto done;
16174 }
16175
16176 s_ptr += 4;
16177 s_len -= 4;
16178 s = (s0 << 18) | (s1 << 12) | (s2 << 6) | (s3 << 0);
16179 *d_ptr++ = (uint8_t)(s >> 16);
16180 *d_ptr++ = (uint8_t)(s >> 8);
16181 *d_ptr++ = (uint8_t)(s >> 0);
16182 d_len -= 3;
16183 }
16184
16185 if (!src_closed) {
16186 o.status.repr = wuffs_base__suspension__short_read;
16187 goto done;
16188 }
16189
16190 if (s_len == 0) {
16191 o.status.repr = NULL;
16192 goto done;
16193 } else if (s_len == 1) {
16194 o.status.repr = wuffs_base__error__bad_data;
16195 goto done;
16196 } else if (s_len == 2) {
16197 goto src2;
16198 }
16199
16200src3:
16201 do {
16202 uint32_t s = wuffs_base__peek_u24le__no_bounds_check(s_ptr);
16203 uint32_t s0 = alphabet[0xFF & (s >> 0)];
16204 uint32_t s1 = alphabet[0xFF & (s >> 8)];
16205 uint32_t s2 = alphabet[0xFF & (s >> 16)];
16206 if ((s0 & 0xC0) || (s1 & 0xC0) || (s2 & 0xC3)) {
16207 o.status.repr = wuffs_base__error__bad_data;
16208 goto done;
16209 }
16210 if (d_len < 2) {
16211 o.status.repr = wuffs_base__suspension__short_write;
16212 goto done;
16213 }
16214 s_ptr += pad ? 4 : 3;
16215 s = (s0 << 18) | (s1 << 12) | (s2 << 6);
16216 *d_ptr++ = (uint8_t)(s >> 16);
16217 *d_ptr++ = (uint8_t)(s >> 8);
16218 o.status.repr = NULL;
16219 goto done;
16220 } while (0);
16221
16222src2:
16223 do {
16224 uint32_t s = wuffs_base__peek_u16le__no_bounds_check(s_ptr);
16225 uint32_t s0 = alphabet[0xFF & (s >> 0)];
16226 uint32_t s1 = alphabet[0xFF & (s >> 8)];
16227 if ((s0 & 0xC0) || (s1 & 0xCF)) {
16228 o.status.repr = wuffs_base__error__bad_data;
16229 goto done;
16230 }
16231 if (d_len < 1) {
16232 o.status.repr = wuffs_base__suspension__short_write;
16233 goto done;
16234 }
16235 s_ptr += pad ? 4 : 2;
16236 s = (s0 << 18) | (s1 << 12);
16237 *d_ptr++ = (uint8_t)(s >> 16);
16238 o.status.repr = NULL;
16239 goto done;
16240 } while (0);
16241
16242done:
16243 o.num_dst = (size_t)(d_ptr - dst.ptr);
16244 o.num_src = (size_t)(s_ptr - src.ptr);
16245 return o;
16246}
16247
16248WUFFS_BASE__MAYBE_STATIC wuffs_base__transform__output //
16249wuffs_base__base_64__encode(wuffs_base__slice_u8 dst,
16250 wuffs_base__slice_u8 src,
16251 bool src_closed,
16252 uint32_t options) {
16253 const uint8_t* alphabet = (options & WUFFS_BASE__BASE_64__URL_ALPHABET)
16254 ? wuffs_base__base_64__encode_url
16255 : wuffs_base__base_64__encode_std;
16256 wuffs_base__transform__output o;
16257 uint8_t* d_ptr = dst.ptr;
16258 size_t d_len = dst.len;
16259 const uint8_t* s_ptr = src.ptr;
16260 size_t s_len = src.len;
16261
16262 do {
16263 while (s_len >= 3) {
16264 if (d_len < 4) {
16265 o.status.repr = wuffs_base__suspension__short_write;
16266 goto done;
16267 }
16268 uint32_t s = wuffs_base__peek_u24be__no_bounds_check(s_ptr);
16269 s_ptr += 3;
16270 s_len -= 3;
16271 *d_ptr++ = alphabet[0x3F & (s >> 18)];
16272 *d_ptr++ = alphabet[0x3F & (s >> 12)];
16273 *d_ptr++ = alphabet[0x3F & (s >> 6)];
16274 *d_ptr++ = alphabet[0x3F & (s >> 0)];
16275 d_len -= 4;
16276 }
16277
16278 if (!src_closed) {
16279 o.status.repr = wuffs_base__suspension__short_read;
16280 goto done;
16281 }
16282
16283 if (s_len == 2) {
16284 if (d_len <
16285 ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 3)) {
16286 o.status.repr = wuffs_base__suspension__short_write;
16287 goto done;
16288 }
16289 uint32_t s = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(s_ptr)))
16290 << 8;
16291 s_ptr += 2;
16292 *d_ptr++ = alphabet[0x3F & (s >> 18)];
16293 *d_ptr++ = alphabet[0x3F & (s >> 12)];
16294 *d_ptr++ = alphabet[0x3F & (s >> 6)];
16295 if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) {
16296 *d_ptr++ = '=';
16297 }
16298 o.status.repr = NULL;
16299 goto done;
16300
16301 } else if (s_len == 1) {
16302 if (d_len <
16303 ((options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) ? 4 : 2)) {
16304 o.status.repr = wuffs_base__suspension__short_write;
16305 goto done;
16306 }
16307 uint32_t s = ((uint32_t)(wuffs_base__peek_u8__no_bounds_check(s_ptr)))
16308 << 16;
16309 s_ptr += 1;
16310 *d_ptr++ = alphabet[0x3F & (s >> 18)];
16311 *d_ptr++ = alphabet[0x3F & (s >> 12)];
16312 if (options & WUFFS_BASE__BASE_64__ENCODE_EMIT_PADDING) {
16313 *d_ptr++ = '=';
16314 *d_ptr++ = '=';
16315 }
16316 o.status.repr = NULL;
16317 goto done;
16318
16319 } else {
16320 o.status.repr = NULL;
16321 goto done;
16322 }
16323 } while (0);
16324
16325done:
16326 o.num_dst = (size_t)(d_ptr - dst.ptr);
16327 o.num_src = (size_t)(s_ptr - src.ptr);
16328 return o;
16329}
16330
16331#endif // !defined(WUFFS_CONFIG__MODULES) ||
16332 // defined(WUFFS_CONFIG__MODULE__BASE) ||
16333 // defined(WUFFS_CONFIG__MODULE__BASE__INTCONV)
16334
16335#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
16336 defined(WUFFS_CONFIG__MODULE__BASE__MAGIC)
16337
16338// ---------------- Magic Numbers
16339
Nigel Taocc74cb42022-01-19 11:06:15 +110016340// ICO doesn't start with a magic identifier. Instead, see if the opening bytes
16341// are plausibly ICO.
16342//
16343// Callers should have already verified that (prefix_data.len >= 2) and the
16344// first two bytes are 0x00.
16345//
16346// See:
16347// - https://docs.fileformat.com/image/ico/
16348static int32_t //
16349wuffs_base__magic_number_guess_fourcc__maybe_ico(
16350 wuffs_base__slice_u8 prefix_data,
16351 bool prefix_closed) {
16352 // Allow-list for the Image Type field.
16353 if (prefix_data.len < 4) {
16354 return prefix_closed ? 0 : -1;
16355 } else if (prefix_data.ptr[3] != 0) {
16356 return 0;
16357 }
16358 switch (prefix_data.ptr[2]) {
16359 case 0x01: // ICO
16360 case 0x02: // CUR
16361 break;
16362 default:
16363 return 0;
16364 }
16365
16366 // The Number Of Images should be positive.
16367 if (prefix_data.len < 6) {
16368 return prefix_closed ? 0 : -1;
16369 } else if ((prefix_data.ptr[4] == 0) && (prefix_data.ptr[5] == 0)) {
16370 return 0;
16371 }
16372
16373 // The first ICONDIRENTRY's fourth byte should be zero.
16374 if (prefix_data.len < 10) {
16375 return prefix_closed ? 0 : -1;
16376 } else if (prefix_data.ptr[9] != 0) {
16377 return 0;
16378 }
16379
16380 // TODO: have a separate FourCC for CUR?
16381 return 0x49434F20; // 'ICO 'be
16382}
16383
16384// TGA doesn't start with a magic identifier. Instead, see if the opening bytes
16385// are plausibly TGA.
16386//
16387// Callers should have already verified that (prefix_data.len >= 2) and the
16388// second byte (prefix_data.ptr[1], the Color Map Type byte), is either 0x00 or
16389// 0x01.
16390//
16391// See:
16392// - https://docs.fileformat.com/image/tga/
16393// - https://www.dca.fee.unicamp.br/~martino/disciplinas/ea978/tgaffs.pdf
16394static int32_t //
16395wuffs_base__magic_number_guess_fourcc__maybe_tga(
16396 wuffs_base__slice_u8 prefix_data,
16397 bool prefix_closed) {
16398 // Allow-list for the Image Type field.
16399 if (prefix_data.len < 3) {
16400 return prefix_closed ? 0 : -1;
16401 }
16402 switch (prefix_data.ptr[2]) {
16403 case 0x01:
16404 case 0x02:
16405 case 0x03:
16406 case 0x09:
16407 case 0x0A:
16408 case 0x0B:
16409 break;
16410 default:
16411 // TODO: 0x20 and 0x21 are invalid, according to the spec, but are
16412 // apparently unofficial extensions.
16413 return 0;
16414 }
16415
16416 // Allow-list for the Color Map Entry Size field (if the Color Map Type field
16417 // is non-zero) or else all the Color Map fields should be zero.
16418 if (prefix_data.len < 8) {
16419 return prefix_closed ? 0 : -1;
16420 } else if (prefix_data.ptr[1] != 0x00) {
16421 switch (prefix_data.ptr[7]) {
16422 case 0x0F:
16423 case 0x10:
16424 case 0x18:
16425 case 0x20:
16426 break;
16427 default:
16428 return 0;
16429 }
16430 } else if ((prefix_data.ptr[3] | prefix_data.ptr[4] | prefix_data.ptr[5] |
16431 prefix_data.ptr[6] | prefix_data.ptr[7]) != 0x00) {
16432 return 0;
16433 }
16434
16435 // Allow-list for the Pixel Depth field.
16436 if (prefix_data.len < 17) {
16437 return prefix_closed ? 0 : -1;
16438 }
16439 switch (prefix_data.ptr[16]) {
16440 case 0x01:
16441 case 0x08:
16442 case 0x0F:
16443 case 0x10:
16444 case 0x18:
16445 case 0x20:
16446 break;
16447 default:
16448 return 0;
16449 }
16450
16451 return 0x54474120; // 'TGA 'be
16452}
16453
Nigel Taoe360a532021-04-05 22:47:03 +100016454WUFFS_BASE__MAYBE_STATIC int32_t //
Nigel Taocc74cb42022-01-19 11:06:15 +110016455wuffs_base__magic_number_guess_fourcc(wuffs_base__slice_u8 prefix_data,
16456 bool prefix_closed) {
16457 // This is similar to (but different from):
16458 // - the magic/Magdir tables under https://github.com/file/file
16459 // - the MIME Sniffing algorithm at https://mimesniff.spec.whatwg.org/
16460
Nigel Taoe360a532021-04-05 22:47:03 +100016461 // table holds the 'magic numbers' (which are actually variable length
16462 // strings). The strings may contain NUL bytes, so the "const char* magic"
16463 // value starts with the length-minus-1 of the 'magic number'.
16464 //
Nigel Tao123a5c62022-06-03 14:17:20 +100016465 // Keep it sorted by magic[1], then magic[0] descending (prioritizing longer
16466 // matches) and finally by magic[2:]. When multiple entries match, the
16467 // longest one wins.
Nigel Taobf9dab32021-11-18 19:19:55 +110016468 //
16469 // The fourcc field might be negated, in which case there's further
16470 // specialization (see § below).
Nigel Taoe360a532021-04-05 22:47:03 +100016471 static struct {
16472 int32_t fourcc;
16473 const char* magic;
16474 } table[] = {
Nigel Taobf9dab32021-11-18 19:19:55 +110016475 {-0x30302020, "\x01\x00\x00"}, // '00 'be
Nigel Tao123a5c62022-06-03 14:17:20 +100016476 {+0x475A2020, "\x02\x1F\x8B\x08"}, // GZ
16477 {+0x5A535444, "\x03\x28\xB5\x2F\xFD"}, // ZSTD
16478 {+0x425A3220, "\x02\x42\x5A\x68"}, // BZ2
Nigel Taobf9dab32021-11-18 19:19:55 +110016479 {+0x424D5020, "\x01\x42\x4D"}, // BMP
16480 {+0x47494620, "\x03\x47\x49\x46\x38"}, // GIF
16481 {+0x54494646, "\x03\x49\x49\x2A\x00"}, // TIFF (little-endian)
16482 {+0x54494646, "\x03\x4D\x4D\x00\x2A"}, // TIFF (big-endian)
16483 {-0x52494646, "\x03\x52\x49\x46\x46"}, // RIFF
16484 {+0x4E494520, "\x02\x6E\xC3\xAF"}, // NIE
Nigel Taoebbecaa2022-01-08 14:08:27 +110016485 {+0x514F4920, "\x03\x71\x6F\x69\x66"}, // QOI
Nigel Tao123a5c62022-06-03 14:17:20 +100016486 {+0x5A4C4942, "\x01\x78\x9C"}, // ZLIB
Nigel Taobf9dab32021-11-18 19:19:55 +110016487 {+0x504E4720, "\x03\x89\x50\x4E\x47"}, // PNG
16488 {+0x4A504547, "\x01\xFF\xD8"}, // JPEG
Nigel Taoe360a532021-04-05 22:47:03 +100016489 };
16490 static const size_t table_len = sizeof(table) / sizeof(table[0]);
16491
Nigel Taocc74cb42022-01-19 11:06:15 +110016492 if (prefix_data.len == 0) {
16493 return prefix_closed ? 0 : -1;
Nigel Taoe360a532021-04-05 22:47:03 +100016494 }
Nigel Taocc74cb42022-01-19 11:06:15 +110016495 uint8_t pre_first_byte = prefix_data.ptr[0];
Nigel Taoe360a532021-04-05 22:47:03 +100016496
16497 int32_t fourcc = 0;
16498 size_t i;
16499 for (i = 0; i < table_len; i++) {
16500 uint8_t mag_first_byte = ((uint8_t)(table[i].magic[1]));
16501 if (pre_first_byte < mag_first_byte) {
16502 break;
16503 } else if (pre_first_byte > mag_first_byte) {
16504 continue;
16505 }
16506 fourcc = table[i].fourcc;
16507
16508 uint8_t mag_remaining_len = ((uint8_t)(table[i].magic[0]));
16509 if (mag_remaining_len == 0) {
16510 goto match;
16511 }
16512
16513 const char* mag_remaining_ptr = table[i].magic + 2;
Nigel Taocc74cb42022-01-19 11:06:15 +110016514 uint8_t* pre_remaining_ptr = prefix_data.ptr + 1;
16515 size_t pre_remaining_len = prefix_data.len - 1;
Nigel Taoe360a532021-04-05 22:47:03 +100016516 if (pre_remaining_len < mag_remaining_len) {
16517 if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, pre_remaining_len)) {
Nigel Taocc74cb42022-01-19 11:06:15 +110016518 return prefix_closed ? 0 : -1;
Nigel Taoe360a532021-04-05 22:47:03 +100016519 }
16520 } else {
16521 if (!memcmp(pre_remaining_ptr, mag_remaining_ptr, mag_remaining_len)) {
16522 goto match;
16523 }
16524 }
16525 }
Nigel Taocc74cb42022-01-19 11:06:15 +110016526
16527 if (prefix_data.len < 2) {
16528 return prefix_closed ? 0 : -1;
16529 } else if ((prefix_data.ptr[1] == 0x00) || (prefix_data.ptr[1] == 0x01)) {
16530 return wuffs_base__magic_number_guess_fourcc__maybe_tga(prefix_data,
16531 prefix_closed);
16532 }
16533
Nigel Taoe360a532021-04-05 22:47:03 +100016534 return 0;
16535
16536match:
Nigel Taobf9dab32021-11-18 19:19:55 +110016537 // Negative FourCC values (see § above) are further specialized.
16538 if (fourcc < 0) {
16539 fourcc = -fourcc;
16540
16541 if (fourcc == 0x52494646) { // 'RIFF'be
Nigel Taocc74cb42022-01-19 11:06:15 +110016542 if (prefix_data.len < 12) {
16543 return prefix_closed ? 0 : -1;
Nigel Taoe360a532021-04-05 22:47:03 +100016544 }
Nigel Taocc74cb42022-01-19 11:06:15 +110016545 uint32_t x = wuffs_base__peek_u32be__no_bounds_check(prefix_data.ptr + 8);
Nigel Taobf9dab32021-11-18 19:19:55 +110016546 if (x == 0x57454250) { // 'WEBP'be
Nigel Taoebbecaa2022-01-08 14:08:27 +110016547 return 0x57454250; // 'WEBP'be
Nigel Taobf9dab32021-11-18 19:19:55 +110016548 }
16549
16550 } else if (fourcc == 0x30302020) { // '00 'be
16551 // Binary data starting with multiple 0x00 NUL bytes is quite common.
Nigel Taocc74cb42022-01-19 11:06:15 +110016552 // Unfortunately, some file formats also don't start with a magic
16553 // identifier, so we have to use heuristics (where the order matters, the
16554 // same as /usr/bin/file's magic/Magdir tables) as best we can. Maybe
16555 // it's TGA, ICO/CUR, etc. Maybe it's something else.
16556 int32_t tga = wuffs_base__magic_number_guess_fourcc__maybe_tga(
16557 prefix_data, prefix_closed);
16558 if (tga != 0) {
16559 return tga;
16560 }
16561 int32_t ico = wuffs_base__magic_number_guess_fourcc__maybe_ico(
16562 prefix_data, prefix_closed);
16563 if (ico != 0) {
16564 return ico;
16565 }
16566 if (prefix_data.len < 4) {
16567 return prefix_closed ? 0 : -1;
16568 } else if ((prefix_data.ptr[2] != 0x00) &&
16569 ((prefix_data.ptr[2] >= 0x80) ||
16570 (prefix_data.ptr[3] != 0x00))) {
Nigel Taobf9dab32021-11-18 19:19:55 +110016571 // Roughly speaking, this could be a non-degenerate (non-0-width and
16572 // non-0-height) WBMP image.
16573 return 0x57424D50; // 'WBMP'be
Nigel Taobf9dab32021-11-18 19:19:55 +110016574 }
16575 return 0;
Nigel Taoe360a532021-04-05 22:47:03 +100016576 }
16577 }
16578 return fourcc;
16579}
16580
16581#endif // !defined(WUFFS_CONFIG__MODULES) ||
16582 // defined(WUFFS_CONFIG__MODULE__BASE) ||
16583 // defined(WUFFS_CONFIG__MODULE__BASE__MAGIC)
16584
16585#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
16586 defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)
16587
16588// ---------------- Pixel Swizzler
16589
16590static inline uint32_t //
16591wuffs_base__swap_u32_argb_abgr(uint32_t u) {
16592 uint32_t o = u & 0xFF00FF00ul;
16593 uint32_t r = u & 0x00FF0000ul;
16594 uint32_t b = u & 0x000000FFul;
16595 return o | (r >> 16) | (b << 16);
16596}
16597
16598static inline uint64_t //
16599wuffs_base__swap_u64_argb_abgr(uint64_t u) {
16600 uint64_t o = u & 0xFFFF0000FFFF0000ull;
16601 uint64_t r = u & 0x0000FFFF00000000ull;
16602 uint64_t b = u & 0x000000000000FFFFull;
16603 return o | (r >> 32) | (b << 32);
16604}
16605
16606static inline uint32_t //
16607wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr(uint64_t c) {
16608 uint32_t a = ((uint32_t)(0xFF & (c >> 56)));
16609 uint32_t r = ((uint32_t)(0xFF & (c >> 40)));
16610 uint32_t g = ((uint32_t)(0xFF & (c >> 24)));
16611 uint32_t b = ((uint32_t)(0xFF & (c >> 8)));
16612 return (a << 24) | (b << 16) | (g << 8) | (r << 0);
16613}
16614
16615// --------
16616
16617WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
16618wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
16619 uint32_t x,
16620 uint32_t y) {
16621 if (!pb || (x >= pb->pixcfg.private_impl.width) ||
16622 (y >= pb->pixcfg.private_impl.height)) {
16623 return 0;
16624 }
16625
16626 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
16627 // TODO: support planar formats.
16628 return 0;
16629 }
16630
16631 size_t stride = pb->private_impl.planes[0].stride;
16632 const uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
16633
16634 switch (pb->pixcfg.private_impl.pixfmt.repr) {
16635 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
16636 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
16637 return wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)));
16638
16639 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
16640 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
16641 uint8_t* palette = pb->private_impl.planes[3].ptr;
16642 return wuffs_base__peek_u32le__no_bounds_check(palette +
16643 (4 * ((size_t)row[x])));
16644 }
16645
16646 // Common formats above. Rarer formats below.
16647
16648 case WUFFS_BASE__PIXEL_FORMAT__Y:
16649 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
16650 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
16651 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 1])));
16652 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
16653 return 0xFF000000 | (0x00010101 * ((uint32_t)(row[(2 * x) + 0])));
16654
16655 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
16656 uint8_t* palette = pb->private_impl.planes[3].ptr;
16657 return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
16658 wuffs_base__peek_u32le__no_bounds_check(palette +
16659 (4 * ((size_t)row[x]))));
16660 }
16661
16662 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
16663 return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
16664 wuffs_base__peek_u16le__no_bounds_check(row + (2 * ((size_t)x))));
16665 case WUFFS_BASE__PIXEL_FORMAT__BGR:
16666 return 0xFF000000 |
16667 wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x)));
16668 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
16669 return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
16670 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
16671 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
16672 return wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
16673 wuffs_base__peek_u64le__no_bounds_check(row + (8 * ((size_t)x))));
16674 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
16675 return 0xFF000000 |
16676 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x)));
16677
16678 case WUFFS_BASE__PIXEL_FORMAT__RGB:
16679 return wuffs_base__swap_u32_argb_abgr(
16680 0xFF000000 |
16681 wuffs_base__peek_u24le__no_bounds_check(row + (3 * ((size_t)x))));
16682 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
16683 return wuffs_base__swap_u32_argb_abgr(
16684 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
16685 wuffs_base__peek_u32le__no_bounds_check(row +
16686 (4 * ((size_t)x)))));
16687 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
16688 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
16689 return wuffs_base__swap_u32_argb_abgr(
16690 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
16691 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
16692 return wuffs_base__swap_u32_argb_abgr(
16693 0xFF000000 |
16694 wuffs_base__peek_u32le__no_bounds_check(row + (4 * ((size_t)x))));
16695
16696 default:
16697 // TODO: support more formats.
16698 break;
16699 }
16700
16701 return 0;
16702}
16703
16704// --------
16705
16706WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
16707wuffs_base__pixel_buffer__set_color_u32_at(
16708 wuffs_base__pixel_buffer* pb,
16709 uint32_t x,
16710 uint32_t y,
16711 wuffs_base__color_u32_argb_premul color) {
16712 if (!pb) {
16713 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
16714 }
16715 if ((x >= pb->pixcfg.private_impl.width) ||
16716 (y >= pb->pixcfg.private_impl.height)) {
16717 return wuffs_base__make_status(wuffs_base__error__bad_argument);
16718 }
16719
16720 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
16721 // TODO: support planar formats.
16722 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
16723 }
16724
16725 size_t stride = pb->private_impl.planes[0].stride;
16726 uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
16727
16728 switch (pb->pixcfg.private_impl.pixfmt.repr) {
16729 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
16730 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
16731 wuffs_base__poke_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
16732 break;
16733
16734 // Common formats above. Rarer formats below.
16735
16736 case WUFFS_BASE__PIXEL_FORMAT__Y:
16737 wuffs_base__poke_u8__no_bounds_check(
16738 row + ((size_t)x),
16739 wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
16740 break;
16741 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
16742 wuffs_base__poke_u16le__no_bounds_check(
16743 row + (2 * ((size_t)x)),
16744 wuffs_base__color_u32_argb_premul__as__color_u16_gray(color));
16745 break;
16746 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
16747 wuffs_base__poke_u16be__no_bounds_check(
16748 row + (2 * ((size_t)x)),
16749 wuffs_base__color_u32_argb_premul__as__color_u16_gray(color));
16750 break;
16751
16752 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
16753 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
16754 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
16755 wuffs_base__poke_u8__no_bounds_check(
16756 row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
16757 wuffs_base__pixel_buffer__palette(pb),
16758 pb->pixcfg.private_impl.pixfmt, color));
16759 break;
16760
16761 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
16762 wuffs_base__poke_u16le__no_bounds_check(
16763 row + (2 * ((size_t)x)),
16764 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
16765 break;
16766 case WUFFS_BASE__PIXEL_FORMAT__BGR:
16767 wuffs_base__poke_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
16768 break;
16769 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
16770 wuffs_base__poke_u32le__no_bounds_check(
16771 row + (4 * ((size_t)x)),
16772 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16773 color));
16774 break;
16775 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
16776 wuffs_base__poke_u64le__no_bounds_check(
16777 row + (8 * ((size_t)x)),
16778 wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
16779 color));
16780 break;
16781
16782 case WUFFS_BASE__PIXEL_FORMAT__RGB:
16783 wuffs_base__poke_u24le__no_bounds_check(
16784 row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
16785 break;
16786 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
16787 wuffs_base__poke_u32le__no_bounds_check(
16788 row + (4 * ((size_t)x)),
16789 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16790 wuffs_base__swap_u32_argb_abgr(color)));
16791 break;
16792 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
16793 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
16794 wuffs_base__poke_u32le__no_bounds_check(
16795 row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
16796 break;
16797
16798 default:
16799 // TODO: support more formats.
16800 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
16801 }
16802
16803 return wuffs_base__make_status(NULL);
16804}
16805
16806// --------
16807
16808static inline void //
16809wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
16810 wuffs_base__pixel_buffer* pb,
16811 wuffs_base__rect_ie_u32 rect,
16812 uint16_t color) {
16813 size_t stride = pb->private_impl.planes[0].stride;
16814 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
16815 if ((stride == (2 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
16816 uint8_t* ptr =
16817 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
16818 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
16819 size_t n;
16820 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
16821 wuffs_base__poke_u16le__no_bounds_check(ptr, color);
16822 ptr += 2;
16823 }
16824 return;
16825 }
16826
16827 uint32_t y;
16828 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16829 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
16830 (2 * ((size_t)rect.min_incl_x));
16831 uint32_t n;
16832 for (n = width; n > 0; n--) {
16833 wuffs_base__poke_u16le__no_bounds_check(ptr, color);
16834 ptr += 2;
16835 }
16836 }
16837}
16838
16839static inline void //
16840wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(
16841 wuffs_base__pixel_buffer* pb,
16842 wuffs_base__rect_ie_u32 rect,
16843 uint32_t color) {
16844 size_t stride = pb->private_impl.planes[0].stride;
16845 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
16846 if ((stride == (3 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
16847 uint8_t* ptr =
16848 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
16849 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
16850 size_t n;
16851 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
16852 wuffs_base__poke_u24le__no_bounds_check(ptr, color);
16853 ptr += 3;
16854 }
16855 return;
16856 }
16857
16858 uint32_t y;
16859 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16860 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
16861 (3 * ((size_t)rect.min_incl_x));
16862 uint32_t n;
16863 for (n = width; n > 0; n--) {
16864 wuffs_base__poke_u24le__no_bounds_check(ptr, color);
16865 ptr += 3;
16866 }
16867 }
16868}
16869
16870static inline void //
16871wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16872 wuffs_base__pixel_buffer* pb,
16873 wuffs_base__rect_ie_u32 rect,
16874 uint32_t color) {
16875 size_t stride = pb->private_impl.planes[0].stride;
16876 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
16877 if ((stride == (4 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
16878 uint8_t* ptr =
16879 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
16880 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
16881 size_t n;
16882 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
16883 wuffs_base__poke_u32le__no_bounds_check(ptr, color);
16884 ptr += 4;
16885 }
16886 return;
16887 }
16888
16889 uint32_t y;
16890 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16891 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
16892 (4 * ((size_t)rect.min_incl_x));
16893 uint32_t n;
16894 for (n = width; n > 0; n--) {
16895 wuffs_base__poke_u32le__no_bounds_check(ptr, color);
16896 ptr += 4;
16897 }
16898 }
16899}
16900
16901static inline void //
16902wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
16903 wuffs_base__pixel_buffer* pb,
16904 wuffs_base__rect_ie_u32 rect,
16905 uint64_t color) {
16906 size_t stride = pb->private_impl.planes[0].stride;
16907 uint32_t width = wuffs_base__rect_ie_u32__width(&rect);
16908 if ((stride == (8 * ((uint64_t)width))) && (rect.min_incl_x == 0)) {
16909 uint8_t* ptr =
16910 pb->private_impl.planes[0].ptr + (stride * ((size_t)rect.min_incl_y));
16911 uint32_t height = wuffs_base__rect_ie_u32__height(&rect);
16912 size_t n;
16913 for (n = ((size_t)width) * ((size_t)height); n > 0; n--) {
16914 wuffs_base__poke_u64le__no_bounds_check(ptr, color);
16915 ptr += 8;
16916 }
16917 return;
16918 }
16919
16920 uint32_t y;
16921 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
16922 uint8_t* ptr = pb->private_impl.planes[0].ptr + (stride * ((size_t)y)) +
16923 (8 * ((size_t)rect.min_incl_x));
16924 uint32_t n;
16925 for (n = width; n > 0; n--) {
16926 wuffs_base__poke_u64le__no_bounds_check(ptr, color);
16927 ptr += 8;
16928 }
16929 }
16930}
16931
16932WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
16933wuffs_base__pixel_buffer__set_color_u32_fill_rect(
16934 wuffs_base__pixel_buffer* pb,
16935 wuffs_base__rect_ie_u32 rect,
16936 wuffs_base__color_u32_argb_premul color) {
16937 if (!pb) {
16938 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
16939 } else if (wuffs_base__rect_ie_u32__is_empty(&rect)) {
16940 return wuffs_base__make_status(NULL);
16941 }
16942 wuffs_base__rect_ie_u32 bounds =
16943 wuffs_base__pixel_config__bounds(&pb->pixcfg);
16944 if (!wuffs_base__rect_ie_u32__contains_rect(&bounds, rect)) {
16945 return wuffs_base__make_status(wuffs_base__error__bad_argument);
16946 }
16947
16948 if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
16949 // TODO: support planar formats.
16950 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
16951 }
16952
16953 switch (pb->pixcfg.private_impl.pixfmt.repr) {
16954 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
16955 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
16956 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(pb, rect, color);
16957 return wuffs_base__make_status(NULL);
16958
16959 // Common formats above. Rarer formats below.
16960
16961 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
16962 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xx(
16963 pb, rect,
16964 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
16965 return wuffs_base__make_status(NULL);
16966
16967 case WUFFS_BASE__PIXEL_FORMAT__BGR:
16968 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxx(pb, rect, color);
16969 return wuffs_base__make_status(NULL);
16970
16971 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
16972 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16973 pb, rect,
16974 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16975 color));
16976 return wuffs_base__make_status(NULL);
16977
16978 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
16979 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxxxxxx(
16980 pb, rect,
16981 wuffs_base__color_u32_argb_premul__as__color_u64_argb_nonpremul(
16982 color));
16983 return wuffs_base__make_status(NULL);
16984
16985 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
16986 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16987 pb, rect,
16988 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
16989 wuffs_base__swap_u32_argb_abgr(color)));
16990 return wuffs_base__make_status(NULL);
16991
16992 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
16993 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
16994 wuffs_base__pixel_buffer__set_color_u32_fill_rect__xxxx(
16995 pb, rect, wuffs_base__swap_u32_argb_abgr(color));
16996 return wuffs_base__make_status(NULL);
16997 }
16998
16999 uint32_t y;
17000 for (y = rect.min_incl_y; y < rect.max_excl_y; y++) {
17001 uint32_t x;
17002 for (x = rect.min_incl_x; x < rect.max_excl_x; x++) {
17003 wuffs_base__pixel_buffer__set_color_u32_at(pb, x, y, color);
17004 }
17005 }
17006 return wuffs_base__make_status(NULL);
17007}
17008
17009// --------
17010
17011WUFFS_BASE__MAYBE_STATIC uint8_t //
17012wuffs_base__pixel_palette__closest_element(
17013 wuffs_base__slice_u8 palette_slice,
17014 wuffs_base__pixel_format palette_format,
17015 wuffs_base__color_u32_argb_premul c) {
17016 size_t n = palette_slice.len / 4;
17017 if (n > (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
17018 n = (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4);
17019 }
17020 size_t best_index = 0;
17021 uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
17022
17023 // Work in 16-bit color.
17024 uint32_t ca = 0x101 * (0xFF & (c >> 24));
17025 uint32_t cr = 0x101 * (0xFF & (c >> 16));
17026 uint32_t cg = 0x101 * (0xFF & (c >> 8));
17027 uint32_t cb = 0x101 * (0xFF & (c >> 0));
17028
17029 switch (palette_format.repr) {
17030 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
17031 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
17032 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
17033 bool nonpremul = palette_format.repr ==
17034 WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
17035
17036 size_t i;
17037 for (i = 0; i < n; i++) {
17038 // Work in 16-bit color.
17039 uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
17040 uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
17041 uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
17042 uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
17043
17044 // Convert to premultiplied alpha.
17045 if (nonpremul && (pa != 0xFFFF)) {
17046 pb = (pb * pa) / 0xFFFF;
17047 pg = (pg * pa) / 0xFFFF;
17048 pr = (pr * pa) / 0xFFFF;
17049 }
17050
17051 // These deltas are conceptually int32_t (signed) but after squaring,
17052 // it's equivalent to work in uint32_t (unsigned).
17053 pb -= cb;
17054 pg -= cg;
17055 pr -= cr;
17056 pa -= ca;
17057 uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
17058 ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
17059 if (best_score > score) {
17060 best_score = score;
17061 best_index = i;
17062 }
17063 }
17064 break;
17065 }
17066 }
17067
17068 return (uint8_t)best_index;
17069}
17070
17071// --------
17072
17073static inline uint32_t //
17074wuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,
17075 uint32_t src_nonpremul) {
17076 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110017077 //
17078 // If the destination is transparent then SRC_OVER is equivalent to SRC: just
17079 // return src_nonpremul. This isn't just an optimization (skipping the rest
17080 // of the function's computation). It also preserves the nonpremul
17081 // distinction between e.g. transparent red and transparent blue that would
17082 // otherwise be lost by converting from nonpremul to premul and back.
17083 uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));
17084 if (da == 0) {
17085 return src_nonpremul;
17086 }
17087 uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));
17088 uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));
17089 uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));
Nigel Taoe360a532021-04-05 22:47:03 +100017090 uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));
17091 uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));
17092 uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));
17093 uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));
Nigel Taoe360a532021-04-05 22:47:03 +100017094
17095 // Convert dst from nonpremul to premul.
17096 dr = (dr * da) / 0xFFFF;
17097 dg = (dg * da) / 0xFFFF;
17098 db = (db * da) / 0xFFFF;
17099
17100 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17101 uint32_t ia = 0xFFFF - sa;
17102
17103 // Composite src (nonpremul) over dst (premul).
17104 da = sa + ((da * ia) / 0xFFFF);
17105 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17106 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17107 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17108
17109 // Convert dst from premul to nonpremul.
17110 if (da != 0) {
17111 dr = (dr * 0xFFFF) / da;
17112 dg = (dg * 0xFFFF) / da;
17113 db = (db * 0xFFFF) / da;
17114 }
17115
17116 // Convert from 16-bit color to 8-bit color.
17117 da >>= 8;
17118 dr >>= 8;
17119 dg >>= 8;
17120 db >>= 8;
17121
17122 // Combine components.
17123 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
17124}
17125
17126static inline uint64_t //
17127wuffs_base__composite_nonpremul_nonpremul_u64_axxx(uint64_t dst_nonpremul,
17128 uint64_t src_nonpremul) {
17129 // Extract components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110017130 //
17131 // If the destination is transparent then SRC_OVER is equivalent to SRC: just
17132 // return src_nonpremul. This isn't just an optimization (skipping the rest
17133 // of the function's computation). It also preserves the nonpremul
17134 // distinction between e.g. transparent red and transparent blue that would
17135 // otherwise be lost by converting from nonpremul to premul and back.
17136 uint64_t da = 0xFFFF & (dst_nonpremul >> 48);
17137 if (da == 0) {
17138 return src_nonpremul;
17139 }
17140 uint64_t dr = 0xFFFF & (dst_nonpremul >> 32);
17141 uint64_t dg = 0xFFFF & (dst_nonpremul >> 16);
17142 uint64_t db = 0xFFFF & (dst_nonpremul >> 0);
Nigel Taoe360a532021-04-05 22:47:03 +100017143 uint64_t sa = 0xFFFF & (src_nonpremul >> 48);
17144 uint64_t sr = 0xFFFF & (src_nonpremul >> 32);
17145 uint64_t sg = 0xFFFF & (src_nonpremul >> 16);
17146 uint64_t sb = 0xFFFF & (src_nonpremul >> 0);
Nigel Taoe360a532021-04-05 22:47:03 +100017147
17148 // Convert dst from nonpremul to premul.
17149 dr = (dr * da) / 0xFFFF;
17150 dg = (dg * da) / 0xFFFF;
17151 db = (db * da) / 0xFFFF;
17152
17153 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17154 uint64_t ia = 0xFFFF - sa;
17155
17156 // Composite src (nonpremul) over dst (premul).
17157 da = sa + ((da * ia) / 0xFFFF);
17158 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17159 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17160 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17161
17162 // Convert dst from premul to nonpremul.
17163 if (da != 0) {
17164 dr = (dr * 0xFFFF) / da;
17165 dg = (dg * 0xFFFF) / da;
17166 db = (db * 0xFFFF) / da;
17167 }
17168
17169 // Combine components.
17170 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
17171}
17172
17173static inline uint32_t //
17174wuffs_base__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul,
17175 uint32_t src_premul) {
17176 // Extract 16-bit color components.
Nigel Taoe360a532021-04-05 22:47:03 +100017177 uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));
17178 uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));
17179 uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));
17180 uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));
Nigel Taoebbecaa2022-01-08 14:08:27 +110017181 uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));
17182 uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));
17183 uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));
17184 uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));
Nigel Taoe360a532021-04-05 22:47:03 +100017185
17186 // Convert dst from nonpremul to premul.
17187 dr = (dr * da) / 0xFFFF;
17188 dg = (dg * da) / 0xFFFF;
17189 db = (db * da) / 0xFFFF;
17190
17191 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17192 uint32_t ia = 0xFFFF - sa;
17193
17194 // Composite src (premul) over dst (premul).
17195 da = sa + ((da * ia) / 0xFFFF);
17196 dr = sr + ((dr * ia) / 0xFFFF);
17197 dg = sg + ((dg * ia) / 0xFFFF);
17198 db = sb + ((db * ia) / 0xFFFF);
17199
17200 // Convert dst from premul to nonpremul.
17201 if (da != 0) {
17202 dr = (dr * 0xFFFF) / da;
17203 dg = (dg * 0xFFFF) / da;
17204 db = (db * 0xFFFF) / da;
17205 }
17206
17207 // Convert from 16-bit color to 8-bit color.
17208 da >>= 8;
17209 dr >>= 8;
17210 dg >>= 8;
17211 db >>= 8;
17212
17213 // Combine components.
17214 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
17215}
17216
17217static inline uint64_t //
17218wuffs_base__composite_nonpremul_premul_u64_axxx(uint64_t dst_nonpremul,
17219 uint64_t src_premul) {
17220 // Extract components.
Nigel Taoe360a532021-04-05 22:47:03 +100017221 uint64_t da = 0xFFFF & (dst_nonpremul >> 48);
17222 uint64_t dr = 0xFFFF & (dst_nonpremul >> 32);
17223 uint64_t dg = 0xFFFF & (dst_nonpremul >> 16);
17224 uint64_t db = 0xFFFF & (dst_nonpremul >> 0);
Nigel Taoebbecaa2022-01-08 14:08:27 +110017225 uint64_t sa = 0xFFFF & (src_premul >> 48);
17226 uint64_t sr = 0xFFFF & (src_premul >> 32);
17227 uint64_t sg = 0xFFFF & (src_premul >> 16);
17228 uint64_t sb = 0xFFFF & (src_premul >> 0);
Nigel Taoe360a532021-04-05 22:47:03 +100017229
17230 // Convert dst from nonpremul to premul.
17231 dr = (dr * da) / 0xFFFF;
17232 dg = (dg * da) / 0xFFFF;
17233 db = (db * da) / 0xFFFF;
17234
17235 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17236 uint64_t ia = 0xFFFF - sa;
17237
17238 // Composite src (premul) over dst (premul).
17239 da = sa + ((da * ia) / 0xFFFF);
17240 dr = sr + ((dr * ia) / 0xFFFF);
17241 dg = sg + ((dg * ia) / 0xFFFF);
17242 db = sb + ((db * ia) / 0xFFFF);
17243
17244 // Convert dst from premul to nonpremul.
17245 if (da != 0) {
17246 dr = (dr * 0xFFFF) / da;
17247 dg = (dg * 0xFFFF) / da;
17248 db = (db * 0xFFFF) / da;
17249 }
17250
17251 // Combine components.
17252 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
17253}
17254
17255static inline uint32_t //
17256wuffs_base__composite_premul_nonpremul_u32_axxx(uint32_t dst_premul,
17257 uint32_t src_nonpremul) {
17258 // Extract 16-bit color components.
Nigel Taoe360a532021-04-05 22:47:03 +100017259 uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));
17260 uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));
17261 uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));
17262 uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));
Nigel Taoebbecaa2022-01-08 14:08:27 +110017263 uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));
17264 uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));
17265 uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));
17266 uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));
Nigel Taoe360a532021-04-05 22:47:03 +100017267
17268 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17269 uint32_t ia = 0xFFFF - sa;
17270
17271 // Composite src (nonpremul) over dst (premul).
17272 da = sa + ((da * ia) / 0xFFFF);
17273 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17274 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17275 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17276
17277 // Convert from 16-bit color to 8-bit color.
17278 da >>= 8;
17279 dr >>= 8;
17280 dg >>= 8;
17281 db >>= 8;
17282
17283 // Combine components.
17284 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
17285}
17286
17287static inline uint64_t //
17288wuffs_base__composite_premul_nonpremul_u64_axxx(uint64_t dst_premul,
17289 uint64_t src_nonpremul) {
17290 // Extract components.
Nigel Taoe360a532021-04-05 22:47:03 +100017291 uint64_t da = 0xFFFF & (dst_premul >> 48);
17292 uint64_t dr = 0xFFFF & (dst_premul >> 32);
17293 uint64_t dg = 0xFFFF & (dst_premul >> 16);
17294 uint64_t db = 0xFFFF & (dst_premul >> 0);
Nigel Taoebbecaa2022-01-08 14:08:27 +110017295 uint64_t sa = 0xFFFF & (src_nonpremul >> 48);
17296 uint64_t sr = 0xFFFF & (src_nonpremul >> 32);
17297 uint64_t sg = 0xFFFF & (src_nonpremul >> 16);
17298 uint64_t sb = 0xFFFF & (src_nonpremul >> 0);
Nigel Taoe360a532021-04-05 22:47:03 +100017299
17300 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17301 uint64_t ia = 0xFFFF - sa;
17302
17303 // Composite src (nonpremul) over dst (premul).
17304 da = sa + ((da * ia) / 0xFFFF);
17305 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17306 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17307 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17308
17309 // Combine components.
17310 return (db << 0) | (dg << 16) | (dr << 32) | (da << 48);
17311}
17312
17313static inline uint32_t //
17314wuffs_base__composite_premul_premul_u32_axxx(uint32_t dst_premul,
17315 uint32_t src_premul) {
17316 // Extract 16-bit color components.
Nigel Taoe360a532021-04-05 22:47:03 +100017317 uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));
17318 uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));
17319 uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));
17320 uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));
Nigel Taoebbecaa2022-01-08 14:08:27 +110017321 uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));
17322 uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));
17323 uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));
17324 uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));
Nigel Taoe360a532021-04-05 22:47:03 +100017325
17326 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17327 uint32_t ia = 0xFFFF - sa;
17328
17329 // Composite src (premul) over dst (premul).
17330 da = sa + ((da * ia) / 0xFFFF);
17331 dr = sr + ((dr * ia) / 0xFFFF);
17332 dg = sg + ((dg * ia) / 0xFFFF);
17333 db = sb + ((db * ia) / 0xFFFF);
17334
17335 // Convert from 16-bit color to 8-bit color.
17336 da >>= 8;
17337 dr >>= 8;
17338 dg >>= 8;
17339 db >>= 8;
17340
17341 // Combine components.
17342 return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);
17343}
17344
17345// --------
17346
17347static uint64_t //
17348wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(uint8_t* dst_ptr,
17349 size_t dst_len,
17350 const uint8_t* src_ptr,
17351 size_t src_len,
17352 bool nonpremul) {
17353 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
17354 uint8_t* d = dst_ptr;
17355 const uint8_t* s = src_ptr;
17356
17357 size_t n = len;
17358 while (n--) {
17359 uint32_t argb = wuffs_base__peek_u32le__no_bounds_check(s);
17360 if (nonpremul) {
17361 argb =
17362 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(argb);
17363 }
17364 uint32_t b5 = 0x1F & (argb >> (8 - 5));
17365 uint32_t g6 = 0x3F & (argb >> (16 - 6));
17366 uint32_t r5 = 0x1F & (argb >> (24 - 5));
17367 uint32_t alpha = argb & 0xFF000000;
17368 wuffs_base__poke_u32le__no_bounds_check(
17369 d, alpha | (r5 << 11) | (g6 << 5) | (b5 << 0));
17370 s += 4;
17371 d += 4;
17372 }
17373 return len;
17374}
17375
17376// --------
17377
17378static uint64_t //
17379wuffs_base__pixel_swizzler__swap_rgb_bgr(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 len = (dst_len < src_len ? dst_len : src_len) / 3;
17386 uint8_t* d = dst_ptr;
17387 const uint8_t* s = src_ptr;
17388
17389 size_t n = len;
17390 while (n--) {
17391 uint8_t s0 = s[0];
17392 uint8_t s1 = s[1];
17393 uint8_t s2 = s[2];
17394 d[0] = s2;
17395 d[1] = s1;
17396 d[2] = s0;
17397 s += 3;
17398 d += 3;
17399 }
17400 return len;
17401}
17402
17403// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110017404#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100017405WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
17406static uint64_t //
17407wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42(uint8_t* dst_ptr,
17408 size_t dst_len,
17409 uint8_t* dst_palette_ptr,
17410 size_t dst_palette_len,
17411 const uint8_t* src_ptr,
17412 size_t src_len) {
17413 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
17414 uint8_t* d = dst_ptr;
17415 const uint8_t* s = src_ptr;
17416 size_t n = len;
17417
17418 __m128i shuffle = _mm_set_epi8(+0x0F, +0x0C, +0x0D, +0x0E, //
17419 +0x0B, +0x08, +0x09, +0x0A, //
17420 +0x07, +0x04, +0x05, +0x06, //
17421 +0x03, +0x00, +0x01, +0x02);
17422
17423 while (n >= 4) {
17424 __m128i x;
17425 x = _mm_lddqu_si128((const __m128i*)(const void*)s);
17426 x = _mm_shuffle_epi8(x, shuffle);
17427 _mm_storeu_si128((__m128i*)(void*)d, x);
17428
17429 s += 4 * 4;
17430 d += 4 * 4;
17431 n -= 4;
17432 }
17433
17434 while (n--) {
17435 uint8_t s0 = s[0];
17436 uint8_t s1 = s[1];
17437 uint8_t s2 = s[2];
17438 uint8_t s3 = s[3];
17439 d[0] = s2;
17440 d[1] = s1;
17441 d[2] = s0;
17442 d[3] = s3;
17443 s += 4;
17444 d += 4;
17445 }
17446 return len;
17447}
Nigel Tao7804ffe2021-10-07 21:58:26 +110017448#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100017449// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
17450
17451static uint64_t //
17452wuffs_base__pixel_swizzler__swap_rgbx_bgrx(uint8_t* dst_ptr,
17453 size_t dst_len,
17454 uint8_t* dst_palette_ptr,
17455 size_t dst_palette_len,
17456 const uint8_t* src_ptr,
17457 size_t src_len) {
17458 size_t len = (dst_len < src_len ? dst_len : src_len) / 4;
17459 uint8_t* d = dst_ptr;
17460 const uint8_t* s = src_ptr;
17461
17462 size_t n = len;
17463 while (n--) {
17464 uint8_t s0 = s[0];
17465 uint8_t s1 = s[1];
17466 uint8_t s2 = s[2];
17467 uint8_t s3 = s[3];
17468 d[0] = s2;
17469 d[1] = s1;
17470 d[2] = s0;
17471 d[3] = s3;
17472 s += 4;
17473 d += 4;
17474 }
17475 return len;
17476}
17477
17478// --------
17479
17480static uint64_t //
17481wuffs_base__pixel_swizzler__copy_1_1(uint8_t* dst_ptr,
17482 size_t dst_len,
17483 uint8_t* dst_palette_ptr,
17484 size_t dst_palette_len,
17485 const uint8_t* src_ptr,
17486 size_t src_len) {
17487 size_t len = (dst_len < src_len) ? dst_len : src_len;
17488 if (len > 0) {
17489 memmove(dst_ptr, src_ptr, len);
17490 }
17491 return len;
17492}
17493
17494static uint64_t //
17495wuffs_base__pixel_swizzler__copy_2_2(uint8_t* dst_ptr,
17496 size_t dst_len,
17497 uint8_t* dst_palette_ptr,
17498 size_t dst_palette_len,
17499 const uint8_t* src_ptr,
17500 size_t src_len) {
17501 size_t dst_len2 = dst_len / 2;
17502 size_t src_len2 = src_len / 2;
17503 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
17504 if (len > 0) {
17505 memmove(dst_ptr, src_ptr, len * 2);
17506 }
17507 return len;
17508}
17509
17510static uint64_t //
17511wuffs_base__pixel_swizzler__copy_3_3(uint8_t* dst_ptr,
17512 size_t dst_len,
17513 uint8_t* dst_palette_ptr,
17514 size_t dst_palette_len,
17515 const uint8_t* src_ptr,
17516 size_t src_len) {
17517 size_t dst_len3 = dst_len / 3;
17518 size_t src_len3 = src_len / 3;
17519 size_t len = (dst_len3 < src_len3) ? dst_len3 : src_len3;
17520 if (len > 0) {
17521 memmove(dst_ptr, src_ptr, len * 3);
17522 }
17523 return len;
17524}
17525
17526static uint64_t //
17527wuffs_base__pixel_swizzler__copy_4_4(uint8_t* dst_ptr,
17528 size_t dst_len,
17529 uint8_t* dst_palette_ptr,
17530 size_t dst_palette_len,
17531 const uint8_t* src_ptr,
17532 size_t src_len) {
17533 size_t dst_len4 = dst_len / 4;
17534 size_t src_len4 = src_len / 4;
17535 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
17536 if (len > 0) {
17537 memmove(dst_ptr, src_ptr, len * 4);
17538 }
17539 return len;
17540}
17541
17542static uint64_t //
17543wuffs_base__pixel_swizzler__copy_8_8(uint8_t* dst_ptr,
17544 size_t dst_len,
17545 uint8_t* dst_palette_ptr,
17546 size_t dst_palette_len,
17547 const uint8_t* src_ptr,
17548 size_t src_len) {
17549 size_t dst_len8 = dst_len / 8;
17550 size_t src_len8 = src_len / 8;
17551 size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8;
17552 if (len > 0) {
17553 memmove(dst_ptr, src_ptr, len * 8);
17554 }
17555 return len;
17556}
17557
17558// --------
17559
17560static uint64_t //
17561wuffs_base__pixel_swizzler__bgr_565__bgr(uint8_t* dst_ptr,
17562 size_t dst_len,
17563 uint8_t* dst_palette_ptr,
17564 size_t dst_palette_len,
17565 const uint8_t* src_ptr,
17566 size_t src_len) {
17567 size_t dst_len2 = dst_len / 2;
17568 size_t src_len3 = src_len / 3;
17569 size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3;
17570 uint8_t* d = dst_ptr;
17571 const uint8_t* s = src_ptr;
17572 size_t n = len;
17573
17574 // TODO: unroll.
17575
17576 while (n >= 1) {
17577 uint32_t b5 = s[0] >> 3;
17578 uint32_t g6 = s[1] >> 2;
17579 uint32_t r5 = s[2] >> 3;
17580 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
17581 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
17582
17583 s += 1 * 3;
17584 d += 1 * 2;
17585 n -= 1;
17586 }
17587
17588 return len;
17589}
17590
17591static uint64_t //
17592wuffs_base__pixel_swizzler__bgr_565__bgrx(uint8_t* dst_ptr,
17593 size_t dst_len,
17594 uint8_t* dst_palette_ptr,
17595 size_t dst_palette_len,
17596 const uint8_t* src_ptr,
17597 size_t src_len) {
17598 size_t dst_len2 = dst_len / 2;
17599 size_t src_len4 = src_len / 4;
17600 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17601 uint8_t* d = dst_ptr;
17602 const uint8_t* s = src_ptr;
17603 size_t n = len;
17604
17605 // TODO: unroll.
17606
17607 while (n >= 1) {
17608 uint32_t b5 = s[0] >> 3;
17609 uint32_t g6 = s[1] >> 2;
17610 uint32_t r5 = s[2] >> 3;
17611 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
17612 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
17613
17614 s += 1 * 4;
17615 d += 1 * 2;
17616 n -= 1;
17617 }
17618
17619 return len;
17620}
17621
17622static uint64_t //
17623wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src(
17624 uint8_t* dst_ptr,
17625 size_t dst_len,
17626 uint8_t* dst_palette_ptr,
17627 size_t dst_palette_len,
17628 const uint8_t* src_ptr,
17629 size_t src_len) {
17630 size_t dst_len2 = dst_len / 2;
17631 size_t src_len4 = src_len / 4;
17632 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17633 uint8_t* d = dst_ptr;
17634 const uint8_t* s = src_ptr;
17635 size_t n = len;
17636
17637 // TODO: unroll.
17638
17639 while (n >= 1) {
17640 wuffs_base__poke_u16le__no_bounds_check(
17641 d + (0 * 2),
17642 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17643 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
17644 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
17645
17646 s += 1 * 4;
17647 d += 1 * 2;
17648 n -= 1;
17649 }
17650
17651 return len;
17652}
17653
17654static uint64_t //
17655wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src(
17656 uint8_t* dst_ptr,
17657 size_t dst_len,
17658 uint8_t* dst_palette_ptr,
17659 size_t dst_palette_len,
17660 const uint8_t* src_ptr,
17661 size_t src_len) {
17662 size_t dst_len2 = dst_len / 2;
17663 size_t src_len8 = src_len / 8;
17664 size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8;
17665 uint8_t* d = dst_ptr;
17666 const uint8_t* s = src_ptr;
17667 size_t n = len;
17668
17669 // TODO: unroll.
17670
17671 while (n >= 1) {
17672 wuffs_base__poke_u16le__no_bounds_check(
17673 d + (0 * 2),
17674 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17675 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
17676 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)))));
17677
17678 s += 1 * 8;
17679 d += 1 * 2;
17680 n -= 1;
17681 }
17682
17683 return len;
17684}
17685
17686static uint64_t //
17687wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over(
17688 uint8_t* dst_ptr,
17689 size_t dst_len,
17690 uint8_t* dst_palette_ptr,
17691 size_t dst_palette_len,
17692 const uint8_t* src_ptr,
17693 size_t src_len) {
17694 size_t dst_len2 = dst_len / 2;
17695 size_t src_len4 = src_len / 4;
17696 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17697 uint8_t* d = dst_ptr;
17698 const uint8_t* s = src_ptr;
17699 size_t n = len;
17700
17701 // TODO: unroll.
17702
17703 while (n >= 1) {
17704 // Extract 16-bit color components.
17705 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17706 uint32_t sr = 0x101 * ((uint32_t)s[2]);
17707 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17708 uint32_t sb = 0x101 * ((uint32_t)s[0]);
17709
17710 // Convert from 565 color to 16-bit color.
17711 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17712 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17713 uint32_t dr = (0x8421 * old_r5) >> 4;
17714 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17715 uint32_t dg = (0x1041 * old_g6) >> 2;
17716 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17717 uint32_t db = (0x8421 * old_b5) >> 4;
17718
17719 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17720 uint32_t ia = 0xFFFF - sa;
17721
17722 // Composite src (nonpremul) over dst (premul).
17723 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17724 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17725 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17726
17727 // Convert from 16-bit color to 565 color and combine the components.
17728 uint32_t new_r5 = 0x1F & (dr >> 11);
17729 uint32_t new_g6 = 0x3F & (dg >> 10);
17730 uint32_t new_b5 = 0x1F & (db >> 11);
17731 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17732 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17733
17734 s += 1 * 4;
17735 d += 1 * 2;
17736 n -= 1;
17737 }
17738
17739 return len;
17740}
17741
17742static uint64_t //
17743wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over(
17744 uint8_t* dst_ptr,
17745 size_t dst_len,
17746 uint8_t* dst_palette_ptr,
17747 size_t dst_palette_len,
17748 const uint8_t* src_ptr,
17749 size_t src_len) {
17750 size_t dst_len2 = dst_len / 2;
17751 size_t src_len8 = src_len / 8;
17752 size_t len = (dst_len2 < src_len8) ? dst_len2 : src_len8;
17753 uint8_t* d = dst_ptr;
17754 const uint8_t* s = src_ptr;
17755 size_t n = len;
17756
17757 // TODO: unroll.
17758
17759 while (n >= 1) {
17760 // Extract 16-bit color components.
17761 uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6));
17762 uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4));
17763 uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2));
17764 uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0));
17765
17766 // Convert from 565 color to 16-bit color.
17767 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17768 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17769 uint32_t dr = (0x8421 * old_r5) >> 4;
17770 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17771 uint32_t dg = (0x1041 * old_g6) >> 2;
17772 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17773 uint32_t db = (0x8421 * old_b5) >> 4;
17774
17775 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17776 uint32_t ia = 0xFFFF - sa;
17777
17778 // Composite src (nonpremul) over dst (premul).
17779 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17780 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17781 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17782
17783 // Convert from 16-bit color to 565 color and combine the components.
17784 uint32_t new_r5 = 0x1F & (dr >> 11);
17785 uint32_t new_g6 = 0x3F & (dg >> 10);
17786 uint32_t new_b5 = 0x1F & (db >> 11);
17787 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17788 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17789
17790 s += 1 * 8;
17791 d += 1 * 2;
17792 n -= 1;
17793 }
17794
17795 return len;
17796}
17797
17798static uint64_t //
17799wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src(uint8_t* dst_ptr,
17800 size_t dst_len,
17801 uint8_t* dst_palette_ptr,
17802 size_t dst_palette_len,
17803 const uint8_t* src_ptr,
17804 size_t src_len) {
17805 size_t dst_len2 = dst_len / 2;
17806 size_t src_len4 = src_len / 4;
17807 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17808 uint8_t* d = dst_ptr;
17809 const uint8_t* s = src_ptr;
17810 size_t n = len;
17811
17812 // TODO: unroll.
17813
17814 while (n >= 1) {
17815 wuffs_base__poke_u16le__no_bounds_check(
17816 d + (0 * 2), wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17817 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
17818
17819 s += 1 * 4;
17820 d += 1 * 2;
17821 n -= 1;
17822 }
17823
17824 return len;
17825}
17826
17827static uint64_t //
17828wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over(
17829 uint8_t* dst_ptr,
17830 size_t dst_len,
17831 uint8_t* dst_palette_ptr,
17832 size_t dst_palette_len,
17833 const uint8_t* src_ptr,
17834 size_t src_len) {
17835 size_t dst_len2 = dst_len / 2;
17836 size_t src_len4 = src_len / 4;
17837 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17838 uint8_t* d = dst_ptr;
17839 const uint8_t* s = src_ptr;
17840 size_t n = len;
17841
17842 // TODO: unroll.
17843
17844 while (n >= 1) {
17845 // Extract 16-bit color components.
17846 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17847 uint32_t sr = 0x101 * ((uint32_t)s[2]);
17848 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17849 uint32_t sb = 0x101 * ((uint32_t)s[0]);
17850
17851 // Convert from 565 color to 16-bit color.
17852 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17853 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17854 uint32_t dr = (0x8421 * old_r5) >> 4;
17855 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17856 uint32_t dg = (0x1041 * old_g6) >> 2;
17857 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17858 uint32_t db = (0x8421 * old_b5) >> 4;
17859
17860 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17861 uint32_t ia = 0xFFFF - sa;
17862
17863 // Composite src (premul) over dst (premul).
17864 dr = sr + ((dr * ia) / 0xFFFF);
17865 dg = sg + ((dg * ia) / 0xFFFF);
17866 db = sb + ((db * ia) / 0xFFFF);
17867
17868 // Convert from 16-bit color to 565 color and combine the components.
17869 uint32_t new_r5 = 0x1F & (dr >> 11);
17870 uint32_t new_g6 = 0x3F & (dg >> 10);
17871 uint32_t new_b5 = 0x1F & (db >> 11);
17872 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17873 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17874
17875 s += 1 * 4;
17876 d += 1 * 2;
17877 n -= 1;
17878 }
17879
17880 return len;
17881}
17882
17883static uint64_t //
17884wuffs_base__pixel_swizzler__bgr_565__rgb(uint8_t* dst_ptr,
17885 size_t dst_len,
17886 uint8_t* dst_palette_ptr,
17887 size_t dst_palette_len,
17888 const uint8_t* src_ptr,
17889 size_t src_len) {
17890 size_t dst_len2 = dst_len / 2;
17891 size_t src_len3 = src_len / 3;
17892 size_t len = (dst_len2 < src_len3) ? dst_len2 : src_len3;
17893 uint8_t* d = dst_ptr;
17894 const uint8_t* s = src_ptr;
17895 size_t n = len;
17896
17897 // TODO: unroll.
17898
17899 while (n >= 1) {
17900 uint32_t r5 = s[0] >> 3;
17901 uint32_t g6 = s[1] >> 2;
17902 uint32_t b5 = s[2] >> 3;
17903 uint32_t rgb_565 = (r5 << 11) | (g6 << 5) | (b5 << 0);
17904 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
17905
17906 s += 1 * 3;
17907 d += 1 * 2;
17908 n -= 1;
17909 }
17910
17911 return len;
17912}
17913
17914static uint64_t //
17915wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src(
17916 uint8_t* dst_ptr,
17917 size_t dst_len,
17918 uint8_t* dst_palette_ptr,
17919 size_t dst_palette_len,
17920 const uint8_t* src_ptr,
17921 size_t src_len) {
17922 size_t dst_len2 = dst_len / 2;
17923 size_t src_len4 = src_len / 4;
17924 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17925 uint8_t* d = dst_ptr;
17926 const uint8_t* s = src_ptr;
17927 size_t n = len;
17928
17929 // TODO: unroll.
17930
17931 while (n >= 1) {
17932 wuffs_base__poke_u16le__no_bounds_check(
17933 d + (0 * 2),
17934 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
17935 wuffs_base__swap_u32_argb_abgr(
17936 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
17937 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))))));
17938
17939 s += 1 * 4;
17940 d += 1 * 2;
17941 n -= 1;
17942 }
17943
17944 return len;
17945}
17946
17947static uint64_t //
17948wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over(
17949 uint8_t* dst_ptr,
17950 size_t dst_len,
17951 uint8_t* dst_palette_ptr,
17952 size_t dst_palette_len,
17953 const uint8_t* src_ptr,
17954 size_t src_len) {
17955 size_t dst_len2 = dst_len / 2;
17956 size_t src_len4 = src_len / 4;
17957 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
17958 uint8_t* d = dst_ptr;
17959 const uint8_t* s = src_ptr;
17960 size_t n = len;
17961
17962 // TODO: unroll.
17963
17964 while (n >= 1) {
17965 // Extract 16-bit color components.
17966 uint32_t sa = 0x101 * ((uint32_t)s[3]);
17967 uint32_t sb = 0x101 * ((uint32_t)s[2]);
17968 uint32_t sg = 0x101 * ((uint32_t)s[1]);
17969 uint32_t sr = 0x101 * ((uint32_t)s[0]);
17970
17971 // Convert from 565 color to 16-bit color.
17972 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
17973 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
17974 uint32_t dr = (0x8421 * old_r5) >> 4;
17975 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
17976 uint32_t dg = (0x1041 * old_g6) >> 2;
17977 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
17978 uint32_t db = (0x8421 * old_b5) >> 4;
17979
17980 // Calculate the inverse of the src-alpha: how much of the dst to keep.
17981 uint32_t ia = 0xFFFF - sa;
17982
17983 // Composite src (nonpremul) over dst (premul).
17984 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
17985 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
17986 db = ((sb * sa) + (db * ia)) / 0xFFFF;
17987
17988 // Convert from 16-bit color to 565 color and combine the components.
17989 uint32_t new_r5 = 0x1F & (dr >> 11);
17990 uint32_t new_g6 = 0x3F & (dg >> 10);
17991 uint32_t new_b5 = 0x1F & (db >> 11);
17992 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
17993 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
17994
17995 s += 1 * 4;
17996 d += 1 * 2;
17997 n -= 1;
17998 }
17999
18000 return len;
18001}
18002
18003static uint64_t //
18004wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src(uint8_t* dst_ptr,
18005 size_t dst_len,
18006 uint8_t* dst_palette_ptr,
18007 size_t dst_palette_len,
18008 const uint8_t* src_ptr,
18009 size_t src_len) {
18010 size_t dst_len2 = dst_len / 2;
18011 size_t src_len4 = src_len / 4;
18012 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
18013 uint8_t* d = dst_ptr;
18014 const uint8_t* s = src_ptr;
18015 size_t n = len;
18016
18017 // TODO: unroll.
18018
18019 while (n >= 1) {
18020 wuffs_base__poke_u16le__no_bounds_check(
18021 d + (0 * 2),
18022 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
18023 wuffs_base__swap_u32_argb_abgr(
18024 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
18025
18026 s += 1 * 4;
18027 d += 1 * 2;
18028 n -= 1;
18029 }
18030
18031 return len;
18032}
18033
18034static uint64_t //
18035wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over(
18036 uint8_t* dst_ptr,
18037 size_t dst_len,
18038 uint8_t* dst_palette_ptr,
18039 size_t dst_palette_len,
18040 const uint8_t* src_ptr,
18041 size_t src_len) {
18042 size_t dst_len2 = dst_len / 2;
18043 size_t src_len4 = src_len / 4;
18044 size_t len = (dst_len2 < src_len4) ? dst_len2 : src_len4;
18045 uint8_t* d = dst_ptr;
18046 const uint8_t* s = src_ptr;
18047 size_t n = len;
18048
18049 // TODO: unroll.
18050
18051 while (n >= 1) {
18052 // Extract 16-bit color components.
18053 uint32_t sa = 0x101 * ((uint32_t)s[3]);
18054 uint32_t sb = 0x101 * ((uint32_t)s[2]);
18055 uint32_t sg = 0x101 * ((uint32_t)s[1]);
18056 uint32_t sr = 0x101 * ((uint32_t)s[0]);
18057
18058 // Convert from 565 color to 16-bit color.
18059 uint32_t old_rgb_565 = wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2));
18060 uint32_t old_r5 = 0x1F & (old_rgb_565 >> 11);
18061 uint32_t dr = (0x8421 * old_r5) >> 4;
18062 uint32_t old_g6 = 0x3F & (old_rgb_565 >> 5);
18063 uint32_t dg = (0x1041 * old_g6) >> 2;
18064 uint32_t old_b5 = 0x1F & (old_rgb_565 >> 0);
18065 uint32_t db = (0x8421 * old_b5) >> 4;
18066
18067 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18068 uint32_t ia = 0xFFFF - sa;
18069
18070 // Composite src (premul) over dst (premul).
18071 dr = sr + ((dr * ia) / 0xFFFF);
18072 dg = sg + ((dg * ia) / 0xFFFF);
18073 db = sb + ((db * ia) / 0xFFFF);
18074
18075 // Convert from 16-bit color to 565 color and combine the components.
18076 uint32_t new_r5 = 0x1F & (dr >> 11);
18077 uint32_t new_g6 = 0x3F & (dg >> 10);
18078 uint32_t new_b5 = 0x1F & (db >> 11);
18079 uint32_t new_rgb_565 = (new_r5 << 11) | (new_g6 << 5) | (new_b5 << 0);
18080 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)new_rgb_565);
18081
18082 s += 1 * 4;
18083 d += 1 * 2;
18084 n -= 1;
18085 }
18086
18087 return len;
18088}
18089
18090static uint64_t //
18091wuffs_base__pixel_swizzler__bgr_565__y(uint8_t* dst_ptr,
18092 size_t dst_len,
18093 uint8_t* dst_palette_ptr,
18094 size_t dst_palette_len,
18095 const uint8_t* src_ptr,
18096 size_t src_len) {
18097 size_t dst_len2 = dst_len / 2;
18098 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
18099 uint8_t* d = dst_ptr;
18100 const uint8_t* s = src_ptr;
18101 size_t n = len;
18102
18103 // TODO: unroll.
18104
18105 while (n >= 1) {
18106 uint32_t y5 = s[0] >> 3;
18107 uint32_t y6 = s[0] >> 2;
18108 uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0);
18109 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
18110
18111 s += 1 * 1;
18112 d += 1 * 2;
18113 n -= 1;
18114 }
18115
18116 return len;
18117}
18118
18119static uint64_t //
18120wuffs_base__pixel_swizzler__bgr_565__y_16be(uint8_t* dst_ptr,
18121 size_t dst_len,
18122 uint8_t* dst_palette_ptr,
18123 size_t dst_palette_len,
18124 const uint8_t* src_ptr,
18125 size_t src_len) {
18126 size_t dst_len2 = dst_len / 2;
18127 size_t src_len2 = src_len / 2;
18128 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
18129 uint8_t* d = dst_ptr;
18130 const uint8_t* s = src_ptr;
18131 size_t n = len;
18132
18133 // TODO: unroll.
18134
18135 while (n >= 1) {
18136 uint32_t y5 = s[0] >> 3;
18137 uint32_t y6 = s[0] >> 2;
18138 uint32_t rgb_565 = (y5 << 11) | (y6 << 5) | (y5 << 0);
18139 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)rgb_565);
18140
18141 s += 1 * 2;
18142 d += 1 * 2;
18143 n -= 1;
18144 }
18145
18146 return len;
18147}
18148
18149static uint64_t //
18150wuffs_base__pixel_swizzler__bgr_565__index__src(uint8_t* dst_ptr,
18151 size_t dst_len,
18152 uint8_t* dst_palette_ptr,
18153 size_t dst_palette_len,
18154 const uint8_t* src_ptr,
18155 size_t src_len) {
18156 if (dst_palette_len !=
18157 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18158 return 0;
18159 }
18160 size_t dst_len2 = dst_len / 2;
18161 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
18162 uint8_t* d = dst_ptr;
18163 const uint8_t* s = src_ptr;
18164 size_t n = len;
18165
18166 const size_t loop_unroll_count = 4;
18167
18168 while (n >= loop_unroll_count) {
18169 wuffs_base__poke_u16le__no_bounds_check(
18170 d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check(
18171 dst_palette_ptr + ((size_t)s[0] * 4)));
18172 wuffs_base__poke_u16le__no_bounds_check(
18173 d + (1 * 2), wuffs_base__peek_u16le__no_bounds_check(
18174 dst_palette_ptr + ((size_t)s[1] * 4)));
18175 wuffs_base__poke_u16le__no_bounds_check(
18176 d + (2 * 2), wuffs_base__peek_u16le__no_bounds_check(
18177 dst_palette_ptr + ((size_t)s[2] * 4)));
18178 wuffs_base__poke_u16le__no_bounds_check(
18179 d + (3 * 2), wuffs_base__peek_u16le__no_bounds_check(
18180 dst_palette_ptr + ((size_t)s[3] * 4)));
18181
18182 s += loop_unroll_count * 1;
18183 d += loop_unroll_count * 2;
18184 n -= loop_unroll_count;
18185 }
18186
18187 while (n >= 1) {
18188 wuffs_base__poke_u16le__no_bounds_check(
18189 d + (0 * 2), wuffs_base__peek_u16le__no_bounds_check(
18190 dst_palette_ptr + ((size_t)s[0] * 4)));
18191
18192 s += 1 * 1;
18193 d += 1 * 2;
18194 n -= 1;
18195 }
18196
18197 return len;
18198}
18199
18200static uint64_t //
18201wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over(
18202 uint8_t* dst_ptr,
18203 size_t dst_len,
18204 uint8_t* dst_palette_ptr,
18205 size_t dst_palette_len,
18206 const uint8_t* src_ptr,
18207 size_t src_len) {
18208 if (dst_palette_len !=
18209 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18210 return 0;
18211 }
18212 size_t dst_len2 = dst_len / 2;
18213 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
18214 uint8_t* d = dst_ptr;
18215 const uint8_t* s = src_ptr;
18216 size_t n = len;
18217
18218 // TODO: unroll.
18219
18220 while (n >= 1) {
18221 uint32_t d0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
18222 wuffs_base__peek_u16le__no_bounds_check(d + (0 * 2)));
18223 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
18224 ((size_t)s[0] * 4));
18225 wuffs_base__poke_u16le__no_bounds_check(
18226 d + (0 * 2),
18227 wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(
18228 wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0)));
18229
18230 s += 1 * 1;
18231 d += 1 * 2;
18232 n -= 1;
18233 }
18234
18235 return len;
18236}
18237
18238static uint64_t //
18239wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over(
18240 uint8_t* dst_ptr,
18241 size_t dst_len,
18242 uint8_t* dst_palette_ptr,
18243 size_t dst_palette_len,
18244 const uint8_t* src_ptr,
18245 size_t src_len) {
18246 if (dst_palette_len !=
18247 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18248 return 0;
18249 }
18250 size_t dst_len2 = dst_len / 2;
18251 size_t len = (dst_len2 < src_len) ? dst_len2 : src_len;
18252 uint8_t* d = dst_ptr;
18253 const uint8_t* s = src_ptr;
18254 size_t n = len;
18255
18256 // TODO: unroll.
18257
18258 while (n >= 1) {
18259 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
18260 ((size_t)s[0] * 4));
18261 if (s0) {
18262 wuffs_base__poke_u16le__no_bounds_check(d + (0 * 2), (uint16_t)s0);
18263 }
18264
18265 s += 1 * 1;
18266 d += 1 * 2;
18267 n -= 1;
18268 }
18269
18270 return len;
18271}
18272
18273// --------
18274
18275static uint64_t //
18276wuffs_base__pixel_swizzler__bgr__bgr_565(uint8_t* dst_ptr,
18277 size_t dst_len,
18278 uint8_t* dst_palette_ptr,
18279 size_t dst_palette_len,
18280 const uint8_t* src_ptr,
18281 size_t src_len) {
18282 size_t dst_len3 = dst_len / 3;
18283 size_t src_len2 = src_len / 2;
18284 size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2;
18285 uint8_t* d = dst_ptr;
18286 const uint8_t* s = src_ptr;
18287 size_t n = len;
18288
18289 // TODO: unroll.
18290
18291 while (n >= 1) {
18292 uint32_t s0 = wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
18293 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)));
18294 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
18295
18296 s += 1 * 2;
18297 d += 1 * 3;
18298 n -= 1;
18299 }
18300
18301 return len;
18302}
18303
18304static uint64_t //
18305wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src(uint8_t* dst_ptr,
18306 size_t dst_len,
18307 uint8_t* dst_palette_ptr,
18308 size_t dst_palette_len,
18309 const uint8_t* src_ptr,
18310 size_t src_len) {
18311 size_t dst_len3 = dst_len / 3;
18312 size_t src_len4 = src_len / 4;
18313 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18314 uint8_t* d = dst_ptr;
18315 const uint8_t* s = src_ptr;
18316 size_t n = len;
18317
18318 // TODO: unroll.
18319
18320 while (n >= 1) {
18321 uint32_t s0 =
18322 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
18323 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18324 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
18325
18326 s += 1 * 4;
18327 d += 1 * 3;
18328 n -= 1;
18329 }
18330
18331 return len;
18332}
18333
18334static uint64_t //
18335wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src(
18336 uint8_t* dst_ptr,
18337 size_t dst_len,
18338 uint8_t* dst_palette_ptr,
18339 size_t dst_palette_len,
18340 const uint8_t* src_ptr,
18341 size_t src_len) {
18342 size_t dst_len3 = dst_len / 3;
18343 size_t src_len8 = src_len / 8;
18344 size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8;
18345 uint8_t* d = dst_ptr;
18346 const uint8_t* s = src_ptr;
18347 size_t n = len;
18348
18349 // TODO: unroll.
18350
18351 while (n >= 1) {
18352 uint32_t s0 =
18353 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
18354 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
18355 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
18356
18357 s += 1 * 8;
18358 d += 1 * 3;
18359 n -= 1;
18360 }
18361
18362 return len;
18363}
18364
18365static uint64_t //
18366wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over(
18367 uint8_t* dst_ptr,
18368 size_t dst_len,
18369 uint8_t* dst_palette_ptr,
18370 size_t dst_palette_len,
18371 const uint8_t* src_ptr,
18372 size_t src_len) {
18373 size_t dst_len3 = dst_len / 3;
18374 size_t src_len4 = src_len / 4;
18375 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18376 uint8_t* d = dst_ptr;
18377 const uint8_t* s = src_ptr;
18378 size_t n = len;
18379
18380 // TODO: unroll.
18381
18382 while (n >= 1) {
18383 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110018384 uint32_t dr = 0x101 * ((uint32_t)d[2]);
18385 uint32_t dg = 0x101 * ((uint32_t)d[1]);
18386 uint32_t db = 0x101 * ((uint32_t)d[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018387 uint32_t sa = 0x101 * ((uint32_t)s[3]);
18388 uint32_t sr = 0x101 * ((uint32_t)s[2]);
18389 uint32_t sg = 0x101 * ((uint32_t)s[1]);
18390 uint32_t sb = 0x101 * ((uint32_t)s[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018391
18392 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18393 uint32_t ia = 0xFFFF - sa;
18394
18395 // Composite src (nonpremul) over dst (premul).
18396 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
18397 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
18398 db = ((sb * sa) + (db * ia)) / 0xFFFF;
18399
18400 // Convert from 16-bit color to 8-bit color.
18401 d[0] = (uint8_t)(db >> 8);
18402 d[1] = (uint8_t)(dg >> 8);
18403 d[2] = (uint8_t)(dr >> 8);
18404
18405 s += 1 * 4;
18406 d += 1 * 3;
18407 n -= 1;
18408 }
18409
18410 return len;
18411}
18412
18413static uint64_t //
18414wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over(
18415 uint8_t* dst_ptr,
18416 size_t dst_len,
18417 uint8_t* dst_palette_ptr,
18418 size_t dst_palette_len,
18419 const uint8_t* src_ptr,
18420 size_t src_len) {
18421 size_t dst_len3 = dst_len / 3;
18422 size_t src_len8 = src_len / 8;
18423 size_t len = (dst_len3 < src_len8) ? dst_len3 : src_len8;
18424 uint8_t* d = dst_ptr;
18425 const uint8_t* s = src_ptr;
18426 size_t n = len;
18427
18428 // TODO: unroll.
18429
18430 while (n >= 1) {
18431 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110018432 uint32_t dr = 0x101 * ((uint32_t)d[2]);
18433 uint32_t dg = 0x101 * ((uint32_t)d[1]);
18434 uint32_t db = 0x101 * ((uint32_t)d[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018435 uint32_t sa = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 6));
18436 uint32_t sr = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 4));
18437 uint32_t sg = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 2));
18438 uint32_t sb = ((uint32_t)wuffs_base__peek_u16le__no_bounds_check(s + 0));
Nigel Taoe360a532021-04-05 22:47:03 +100018439
18440 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18441 uint32_t ia = 0xFFFF - sa;
18442
18443 // Composite src (nonpremul) over dst (premul).
18444 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
18445 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
18446 db = ((sb * sa) + (db * ia)) / 0xFFFF;
18447
18448 // Convert from 16-bit color to 8-bit color.
18449 d[0] = (uint8_t)(db >> 8);
18450 d[1] = (uint8_t)(dg >> 8);
18451 d[2] = (uint8_t)(dr >> 8);
18452
18453 s += 1 * 8;
18454 d += 1 * 3;
18455 n -= 1;
18456 }
18457
18458 return len;
18459}
18460
18461static uint64_t //
18462wuffs_base__pixel_swizzler__bgr__bgra_premul__src(uint8_t* dst_ptr,
18463 size_t dst_len,
18464 uint8_t* dst_palette_ptr,
18465 size_t dst_palette_len,
18466 const uint8_t* src_ptr,
18467 size_t src_len) {
18468 size_t dst_len3 = dst_len / 3;
18469 size_t src_len4 = src_len / 4;
18470 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18471 uint8_t* d = dst_ptr;
18472 const uint8_t* s = src_ptr;
18473 size_t n = len;
18474
18475 while (n >= 1) {
18476 uint8_t s0 = s[0];
18477 uint8_t s1 = s[1];
18478 uint8_t s2 = s[2];
18479 d[0] = s0;
18480 d[1] = s1;
18481 d[2] = s2;
18482
18483 s += 1 * 4;
18484 d += 1 * 3;
18485 n -= 1;
18486 }
18487
18488 return len;
18489}
18490
18491static uint64_t //
18492wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over(uint8_t* dst_ptr,
18493 size_t dst_len,
18494 uint8_t* dst_palette_ptr,
18495 size_t dst_palette_len,
18496 const uint8_t* src_ptr,
18497 size_t src_len) {
18498 size_t dst_len3 = dst_len / 3;
18499 size_t src_len4 = src_len / 4;
18500 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18501 uint8_t* d = dst_ptr;
18502 const uint8_t* s = src_ptr;
18503 size_t n = len;
18504
18505 while (n >= 1) {
18506 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110018507 uint32_t dr = 0x101 * ((uint32_t)d[2]);
18508 uint32_t dg = 0x101 * ((uint32_t)d[1]);
18509 uint32_t db = 0x101 * ((uint32_t)d[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018510 uint32_t sa = 0x101 * ((uint32_t)s[3]);
18511 uint32_t sr = 0x101 * ((uint32_t)s[2]);
18512 uint32_t sg = 0x101 * ((uint32_t)s[1]);
18513 uint32_t sb = 0x101 * ((uint32_t)s[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018514
18515 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18516 uint32_t ia = 0xFFFF - sa;
18517
18518 // Composite src (premul) over dst (premul).
18519 dr = sr + ((dr * ia) / 0xFFFF);
18520 dg = sg + ((dg * ia) / 0xFFFF);
18521 db = sb + ((db * ia) / 0xFFFF);
18522
18523 // Convert from 16-bit color to 8-bit color.
18524 d[0] = (uint8_t)(db >> 8);
18525 d[1] = (uint8_t)(dg >> 8);
18526 d[2] = (uint8_t)(dr >> 8);
18527
18528 s += 1 * 4;
18529 d += 1 * 3;
18530 n -= 1;
18531 }
18532
18533 return len;
18534}
18535
18536static uint64_t //
18537wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src(uint8_t* dst_ptr,
18538 size_t dst_len,
18539 uint8_t* dst_palette_ptr,
18540 size_t dst_palette_len,
18541 const uint8_t* src_ptr,
18542 size_t src_len) {
18543 size_t dst_len3 = dst_len / 3;
18544 size_t src_len4 = src_len / 4;
18545 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18546 uint8_t* d = dst_ptr;
18547 const uint8_t* s = src_ptr;
18548 size_t n = len;
18549
18550 // TODO: unroll.
18551
18552 while (n >= 1) {
18553 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18554 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
18555 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
18556 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
18557
18558 s += 1 * 4;
18559 d += 1 * 3;
18560 n -= 1;
18561 }
18562
18563 return len;
18564}
18565
18566static uint64_t //
18567wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over(
18568 uint8_t* dst_ptr,
18569 size_t dst_len,
18570 uint8_t* dst_palette_ptr,
18571 size_t dst_palette_len,
18572 const uint8_t* src_ptr,
18573 size_t src_len) {
18574 size_t dst_len3 = dst_len / 3;
18575 size_t src_len4 = src_len / 4;
18576 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18577 uint8_t* d = dst_ptr;
18578 const uint8_t* s = src_ptr;
18579 size_t n = len;
18580
18581 // TODO: unroll.
18582
18583 while (n >= 1) {
18584 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110018585 uint32_t dr = 0x101 * ((uint32_t)d[2]);
18586 uint32_t dg = 0x101 * ((uint32_t)d[1]);
18587 uint32_t db = 0x101 * ((uint32_t)d[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018588 uint32_t sa = 0x101 * ((uint32_t)s[3]);
18589 uint32_t sb = 0x101 * ((uint32_t)s[2]);
18590 uint32_t sg = 0x101 * ((uint32_t)s[1]);
18591 uint32_t sr = 0x101 * ((uint32_t)s[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018592
18593 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18594 uint32_t ia = 0xFFFF - sa;
18595
18596 // Composite src (nonpremul) over dst (premul).
18597 dr = ((sr * sa) + (dr * ia)) / 0xFFFF;
18598 dg = ((sg * sa) + (dg * ia)) / 0xFFFF;
18599 db = ((sb * sa) + (db * ia)) / 0xFFFF;
18600
18601 // Convert from 16-bit color to 8-bit color.
18602 d[0] = (uint8_t)(db >> 8);
18603 d[1] = (uint8_t)(dg >> 8);
18604 d[2] = (uint8_t)(dr >> 8);
18605
18606 s += 1 * 4;
18607 d += 1 * 3;
18608 n -= 1;
18609 }
18610
18611 return len;
18612}
18613
18614static uint64_t //
18615wuffs_base__pixel_swizzler__bgr__rgba_premul__src(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_len3 = dst_len / 3;
18622 size_t src_len4 = src_len / 4;
18623 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18624 uint8_t* d = dst_ptr;
18625 const uint8_t* s = src_ptr;
18626 size_t n = len;
18627
18628 while (n >= 1) {
18629 uint8_t s0 = s[0];
18630 uint8_t s1 = s[1];
18631 uint8_t s2 = s[2];
18632 d[0] = s2;
18633 d[1] = s1;
18634 d[2] = s0;
18635
18636 s += 1 * 4;
18637 d += 1 * 3;
18638 n -= 1;
18639 }
18640
18641 return len;
18642}
18643
18644static uint64_t //
18645wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over(uint8_t* dst_ptr,
18646 size_t dst_len,
18647 uint8_t* dst_palette_ptr,
18648 size_t dst_palette_len,
18649 const uint8_t* src_ptr,
18650 size_t src_len) {
18651 size_t dst_len3 = dst_len / 3;
18652 size_t src_len4 = src_len / 4;
18653 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
18654 uint8_t* d = dst_ptr;
18655 const uint8_t* s = src_ptr;
18656 size_t n = len;
18657
18658 while (n >= 1) {
18659 // Extract 16-bit color components.
Nigel Taoebbecaa2022-01-08 14:08:27 +110018660 uint32_t dr = 0x101 * ((uint32_t)d[2]);
18661 uint32_t dg = 0x101 * ((uint32_t)d[1]);
18662 uint32_t db = 0x101 * ((uint32_t)d[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018663 uint32_t sa = 0x101 * ((uint32_t)s[3]);
18664 uint32_t sb = 0x101 * ((uint32_t)s[2]);
18665 uint32_t sg = 0x101 * ((uint32_t)s[1]);
18666 uint32_t sr = 0x101 * ((uint32_t)s[0]);
Nigel Taoe360a532021-04-05 22:47:03 +100018667
18668 // Calculate the inverse of the src-alpha: how much of the dst to keep.
18669 uint32_t ia = 0xFFFF - sa;
18670
18671 // Composite src (premul) over dst (premul).
18672 dr = sr + ((dr * ia) / 0xFFFF);
18673 dg = sg + ((dg * ia) / 0xFFFF);
18674 db = sb + ((db * ia) / 0xFFFF);
18675
18676 // Convert from 16-bit color to 8-bit color.
18677 d[0] = (uint8_t)(db >> 8);
18678 d[1] = (uint8_t)(dg >> 8);
18679 d[2] = (uint8_t)(dr >> 8);
18680
18681 s += 1 * 4;
18682 d += 1 * 3;
18683 n -= 1;
18684 }
18685
18686 return len;
18687}
18688
18689// --------
18690
18691static uint64_t //
18692wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over(
18693 uint8_t* dst_ptr,
18694 size_t dst_len,
18695 uint8_t* dst_palette_ptr,
18696 size_t dst_palette_len,
18697 const uint8_t* src_ptr,
18698 size_t src_len) {
18699 size_t dst_len4 = dst_len / 4;
18700 size_t src_len4 = src_len / 4;
18701 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18702 uint8_t* d = dst_ptr;
18703 const uint8_t* s = src_ptr;
18704 size_t n = len;
18705
18706 while (n >= 1) {
18707 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18708 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18709 wuffs_base__poke_u32le__no_bounds_check(
18710 d + (0 * 4),
18711 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
18712
18713 s += 1 * 4;
18714 d += 1 * 4;
18715 n -= 1;
18716 }
18717
18718 return len;
18719}
18720
18721static uint64_t //
18722wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src(
18723 uint8_t* dst_ptr,
18724 size_t dst_len,
18725 uint8_t* dst_palette_ptr,
18726 size_t dst_palette_len,
18727 const uint8_t* src_ptr,
18728 size_t src_len) {
18729 size_t dst_len4 = dst_len / 4;
18730 size_t src_len8 = src_len / 8;
18731 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18732 uint8_t* d = dst_ptr;
18733 const uint8_t* s = src_ptr;
18734
18735 size_t n = len;
18736 while (n >= 1) {
18737 wuffs_base__poke_u32le__no_bounds_check(
18738 d + (0 * 4), wuffs_base__color_u64__as__color_u32(
18739 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))));
18740
18741 s += 1 * 8;
18742 d += 1 * 4;
18743 n -= 1;
18744 }
18745 return len;
18746}
18747
18748static uint64_t //
18749wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over(
18750 uint8_t* dst_ptr,
18751 size_t dst_len,
18752 uint8_t* dst_palette_ptr,
18753 size_t dst_palette_len,
18754 const uint8_t* src_ptr,
18755 size_t src_len) {
18756 size_t dst_len4 = dst_len / 4;
18757 size_t src_len8 = src_len / 8;
18758 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
18759 uint8_t* d = dst_ptr;
18760 const uint8_t* s = src_ptr;
18761 size_t n = len;
18762
18763 while (n >= 1) {
18764 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
18765 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
18766 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
18767 wuffs_base__poke_u32le__no_bounds_check(
18768 d + (0 * 4),
18769 wuffs_base__color_u64__as__color_u32(
18770 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)));
18771
18772 s += 1 * 8;
18773 d += 1 * 4;
18774 n -= 1;
18775 }
18776
18777 return len;
18778}
18779
18780static uint64_t //
18781wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src(
18782 uint8_t* dst_ptr,
18783 size_t dst_len,
18784 uint8_t* dst_palette_ptr,
18785 size_t dst_palette_len,
18786 const uint8_t* src_ptr,
18787 size_t src_len) {
18788 size_t dst_len4 = dst_len / 4;
18789 size_t src_len4 = src_len / 4;
18790 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18791 uint8_t* d = dst_ptr;
18792 const uint8_t* s = src_ptr;
18793 size_t n = len;
18794
18795 while (n >= 1) {
18796 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18797 wuffs_base__poke_u32le__no_bounds_check(
18798 d + (0 * 4),
18799 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0));
18800
18801 s += 1 * 4;
18802 d += 1 * 4;
18803 n -= 1;
18804 }
18805
18806 return len;
18807}
18808
18809static uint64_t //
18810wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over(
18811 uint8_t* dst_ptr,
18812 size_t dst_len,
18813 uint8_t* dst_palette_ptr,
18814 size_t dst_palette_len,
18815 const uint8_t* src_ptr,
18816 size_t src_len) {
18817 size_t dst_len4 = dst_len / 4;
18818 size_t src_len4 = src_len / 4;
18819 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18820 uint8_t* d = dst_ptr;
18821 const uint8_t* s = src_ptr;
18822 size_t n = len;
18823
18824 while (n >= 1) {
18825 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18826 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
18827 wuffs_base__poke_u32le__no_bounds_check(
18828 d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0));
18829
18830 s += 1 * 4;
18831 d += 1 * 4;
18832 n -= 1;
18833 }
18834
18835 return len;
18836}
18837
18838static uint64_t //
18839wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over(
18840 uint8_t* dst_ptr,
18841 size_t dst_len,
18842 uint8_t* dst_palette_ptr,
18843 size_t dst_palette_len,
18844 const uint8_t* src_ptr,
18845 size_t src_len) {
18846 if (dst_palette_len !=
18847 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
18848 return 0;
18849 }
18850 size_t dst_len4 = dst_len / 4;
18851 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
18852 uint8_t* d = dst_ptr;
18853 const uint8_t* s = src_ptr;
18854 size_t n = len;
18855
18856 // TODO: unroll.
18857
18858 while (n >= 1) {
18859 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18860 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
18861 ((size_t)s[0] * 4));
18862 wuffs_base__poke_u32le__no_bounds_check(
18863 d + (0 * 4),
18864 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
18865
18866 s += 1 * 1;
18867 d += 1 * 4;
18868 n -= 1;
18869 }
18870
18871 return len;
18872}
18873
18874static uint64_t //
18875wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over(
18876 uint8_t* dst_ptr,
18877 size_t dst_len,
18878 uint8_t* dst_palette_ptr,
18879 size_t dst_palette_len,
18880 const uint8_t* src_ptr,
18881 size_t src_len) {
18882 size_t dst_len4 = dst_len / 4;
18883 size_t src_len4 = src_len / 4;
18884 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18885 uint8_t* d = dst_ptr;
18886 const uint8_t* s = src_ptr;
18887 size_t n = len;
18888
18889 while (n >= 1) {
18890 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18891 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18892 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18893 wuffs_base__poke_u32le__no_bounds_check(
18894 d + (0 * 4),
18895 wuffs_base__composite_nonpremul_nonpremul_u32_axxx(d0, s0));
18896
18897 s += 1 * 4;
18898 d += 1 * 4;
18899 n -= 1;
18900 }
18901
18902 return len;
18903}
18904
18905static uint64_t //
18906wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src(
18907 uint8_t* dst_ptr,
18908 size_t dst_len,
18909 uint8_t* dst_palette_ptr,
18910 size_t dst_palette_len,
18911 const uint8_t* src_ptr,
18912 size_t src_len) {
18913 size_t dst_len4 = dst_len / 4;
18914 size_t src_len4 = src_len / 4;
18915 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18916 uint8_t* d = dst_ptr;
18917 const uint8_t* s = src_ptr;
18918 size_t n = len;
18919
18920 while (n >= 1) {
18921 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18922 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18923 wuffs_base__poke_u32le__no_bounds_check(
18924 d + (0 * 4),
18925 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(s0));
18926
18927 s += 1 * 4;
18928 d += 1 * 4;
18929 n -= 1;
18930 }
18931
18932 return len;
18933}
18934
18935static uint64_t //
18936wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over(
18937 uint8_t* dst_ptr,
18938 size_t dst_len,
18939 uint8_t* dst_palette_ptr,
18940 size_t dst_palette_len,
18941 const uint8_t* src_ptr,
18942 size_t src_len) {
18943 size_t dst_len4 = dst_len / 4;
18944 size_t src_len4 = src_len / 4;
18945 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
18946 uint8_t* d = dst_ptr;
18947 const uint8_t* s = src_ptr;
18948 size_t n = len;
18949
18950 while (n >= 1) {
18951 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
18952 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
18953 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
18954 wuffs_base__poke_u32le__no_bounds_check(
18955 d + (0 * 4), wuffs_base__composite_nonpremul_premul_u32_axxx(d0, s0));
18956
18957 s += 1 * 4;
18958 d += 1 * 4;
18959 n -= 1;
18960 }
18961
18962 return len;
18963}
18964
18965// --------
18966
18967static uint64_t //
18968wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src(
18969 uint8_t* dst_ptr,
18970 size_t dst_len,
18971 uint8_t* dst_palette_ptr,
18972 size_t dst_palette_len,
18973 const uint8_t* src_ptr,
18974 size_t src_len) {
18975 size_t dst_len8 = dst_len / 8;
18976 size_t src_len4 = src_len / 4;
18977 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
18978 uint8_t* d = dst_ptr;
18979 const uint8_t* s = src_ptr;
18980
18981 size_t n = len;
18982 while (n >= 1) {
18983 uint8_t s0 = s[0];
18984 uint8_t s1 = s[1];
18985 uint8_t s2 = s[2];
18986 uint8_t s3 = s[3];
18987 d[0] = s0;
18988 d[1] = s0;
18989 d[2] = s1;
18990 d[3] = s1;
18991 d[4] = s2;
18992 d[5] = s2;
18993 d[6] = s3;
18994 d[7] = s3;
18995
18996 s += 1 * 4;
18997 d += 1 * 8;
18998 n -= 1;
18999 }
19000 return len;
19001}
19002
19003static uint64_t //
19004wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over(
19005 uint8_t* dst_ptr,
19006 size_t dst_len,
19007 uint8_t* dst_palette_ptr,
19008 size_t dst_palette_len,
19009 const uint8_t* src_ptr,
19010 size_t src_len) {
19011 size_t dst_len8 = dst_len / 8;
19012 size_t src_len4 = src_len / 4;
19013 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19014 uint8_t* d = dst_ptr;
19015 const uint8_t* s = src_ptr;
19016
19017 size_t n = len;
19018 while (n >= 1) {
19019 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19020 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
19021 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19022 wuffs_base__poke_u64le__no_bounds_check(
19023 d + (0 * 8),
19024 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
19025
19026 s += 1 * 4;
19027 d += 1 * 8;
19028 n -= 1;
19029 }
19030 return len;
19031}
19032
19033static uint64_t //
19034wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over(
19035 uint8_t* dst_ptr,
19036 size_t dst_len,
19037 uint8_t* dst_palette_ptr,
19038 size_t dst_palette_len,
19039 const uint8_t* src_ptr,
19040 size_t src_len) {
19041 size_t dst_len8 = dst_len / 8;
19042 size_t src_len8 = src_len / 8;
19043 size_t len = (dst_len8 < src_len8) ? dst_len8 : src_len8;
19044 uint8_t* d = dst_ptr;
19045 const uint8_t* s = src_ptr;
19046
19047 size_t n = len;
19048 while (n >= 1) {
19049 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19050 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
19051 wuffs_base__poke_u64le__no_bounds_check(
19052 d + (0 * 8),
19053 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
19054
19055 s += 1 * 8;
19056 d += 1 * 8;
19057 n -= 1;
19058 }
19059 return len;
19060}
19061
19062static uint64_t //
19063wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src(
19064 uint8_t* dst_ptr,
19065 size_t dst_len,
19066 uint8_t* dst_palette_ptr,
19067 size_t dst_palette_len,
19068 const uint8_t* src_ptr,
19069 size_t src_len) {
19070 size_t dst_len8 = dst_len / 8;
19071 size_t src_len4 = src_len / 4;
19072 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19073 uint8_t* d = dst_ptr;
19074 const uint8_t* s = src_ptr;
19075
19076 size_t n = len;
19077 while (n >= 1) {
19078 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
19079 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
19080 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
19081 wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0);
19082
19083 s += 1 * 4;
19084 d += 1 * 8;
19085 n -= 1;
19086 }
19087 return len;
19088}
19089
19090static uint64_t //
19091wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over(
19092 uint8_t* dst_ptr,
19093 size_t dst_len,
19094 uint8_t* dst_palette_ptr,
19095 size_t dst_palette_len,
19096 const uint8_t* src_ptr,
19097 size_t src_len) {
19098 size_t dst_len8 = dst_len / 8;
19099 size_t src_len4 = src_len / 4;
19100 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19101 uint8_t* d = dst_ptr;
19102 const uint8_t* s = src_ptr;
19103
19104 size_t n = len;
19105 while (n >= 1) {
19106 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19107 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
19108 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19109 wuffs_base__poke_u64le__no_bounds_check(
19110 d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0));
19111
19112 s += 1 * 4;
19113 d += 1 * 8;
19114 n -= 1;
19115 }
19116 return len;
19117}
19118
19119static uint64_t //
19120wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over(
19121 uint8_t* dst_ptr,
19122 size_t dst_len,
19123 uint8_t* dst_palette_ptr,
19124 size_t dst_palette_len,
19125 const uint8_t* src_ptr,
19126 size_t src_len) {
19127 if (dst_palette_len !=
19128 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19129 return 0;
19130 }
19131 size_t dst_len8 = dst_len / 8;
19132 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
19133 uint8_t* d = dst_ptr;
19134 const uint8_t* s = src_ptr;
19135 size_t n = len;
19136
19137 while (n >= 1) {
19138 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19139 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
19140 wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19141 ((size_t)s[0] * 4)));
19142 wuffs_base__poke_u64le__no_bounds_check(
19143 d + (0 * 8),
19144 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
19145
19146 s += 1 * 1;
19147 d += 1 * 8;
19148 n -= 1;
19149 }
19150
19151 return len;
19152}
19153
19154static uint64_t //
19155wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src(
19156 uint8_t* dst_ptr,
19157 size_t dst_len,
19158 uint8_t* dst_palette_ptr,
19159 size_t dst_palette_len,
19160 const uint8_t* src_ptr,
19161 size_t src_len) {
19162 size_t dst_len8 = dst_len / 8;
19163 size_t src_len4 = src_len / 4;
19164 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19165 uint8_t* d = dst_ptr;
19166 const uint8_t* s = src_ptr;
19167
19168 size_t n = len;
19169 while (n >= 1) {
19170 uint8_t s0 = s[0];
19171 uint8_t s1 = s[1];
19172 uint8_t s2 = s[2];
19173 uint8_t s3 = s[3];
19174 d[0] = s2;
19175 d[1] = s2;
19176 d[2] = s1;
19177 d[3] = s1;
19178 d[4] = s0;
19179 d[5] = s0;
19180 d[6] = s3;
19181 d[7] = s3;
19182
19183 s += 1 * 4;
19184 d += 1 * 8;
19185 n -= 1;
19186 }
19187 return len;
19188}
19189
19190static uint64_t //
19191wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over(
19192 uint8_t* dst_ptr,
19193 size_t dst_len,
19194 uint8_t* dst_palette_ptr,
19195 size_t dst_palette_len,
19196 const uint8_t* src_ptr,
19197 size_t src_len) {
19198 size_t dst_len8 = dst_len / 8;
19199 size_t src_len4 = src_len / 4;
19200 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19201 uint8_t* d = dst_ptr;
19202 const uint8_t* s = src_ptr;
19203
19204 size_t n = len;
19205 while (n >= 1) {
19206 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19207 uint64_t s0 =
19208 wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr(
19209 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
19210 wuffs_base__poke_u64le__no_bounds_check(
19211 d + (0 * 8),
19212 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0));
19213
19214 s += 1 * 4;
19215 d += 1 * 8;
19216 n -= 1;
19217 }
19218 return len;
19219}
19220
19221static uint64_t //
19222wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src(
19223 uint8_t* dst_ptr,
19224 size_t dst_len,
19225 uint8_t* dst_palette_ptr,
19226 size_t dst_palette_len,
19227 const uint8_t* src_ptr,
19228 size_t src_len) {
19229 size_t dst_len8 = dst_len / 8;
19230 size_t src_len4 = src_len / 4;
19231 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19232 uint8_t* d = dst_ptr;
19233 const uint8_t* s = src_ptr;
19234
19235 size_t n = len;
19236 while (n >= 1) {
19237 uint64_t s0 = wuffs_base__color_u32__as__color_u64(
19238 wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
19239 wuffs_base__swap_u32_argb_abgr(
19240 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)))));
19241 wuffs_base__poke_u64le__no_bounds_check(d + (0 * 8), s0);
19242
19243 s += 1 * 4;
19244 d += 1 * 8;
19245 n -= 1;
19246 }
19247 return len;
19248}
19249
19250static uint64_t //
19251wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over(
19252 uint8_t* dst_ptr,
19253 size_t dst_len,
19254 uint8_t* dst_palette_ptr,
19255 size_t dst_palette_len,
19256 const uint8_t* src_ptr,
19257 size_t src_len) {
19258 size_t dst_len8 = dst_len / 8;
19259 size_t src_len4 = src_len / 4;
19260 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19261 uint8_t* d = dst_ptr;
19262 const uint8_t* s = src_ptr;
19263
19264 size_t n = len;
19265 while (n >= 1) {
19266 uint64_t d0 = wuffs_base__peek_u64le__no_bounds_check(d + (0 * 8));
19267 uint64_t s0 =
19268 wuffs_base__color_u32__as__color_u64(wuffs_base__swap_u32_argb_abgr(
19269 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4))));
19270 wuffs_base__poke_u64le__no_bounds_check(
19271 d + (0 * 8), wuffs_base__composite_nonpremul_premul_u64_axxx(d0, s0));
19272
19273 s += 1 * 4;
19274 d += 1 * 8;
19275 n -= 1;
19276 }
19277 return len;
19278}
19279
19280// --------
19281
19282static uint64_t //
19283wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
19284 uint8_t* dst_ptr,
19285 size_t dst_len,
19286 uint8_t* dst_palette_ptr,
19287 size_t dst_palette_len,
19288 const uint8_t* src_ptr,
19289 size_t src_len) {
19290 size_t dst_len4 = dst_len / 4;
19291 size_t src_len4 = src_len / 4;
19292 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19293 uint8_t* d = dst_ptr;
19294 const uint8_t* s = src_ptr;
19295 size_t n = len;
19296
19297 // TODO: unroll.
19298
19299 while (n >= 1) {
19300 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
19301 wuffs_base__poke_u32le__no_bounds_check(
19302 d + (0 * 4),
19303 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0));
19304
19305 s += 1 * 4;
19306 d += 1 * 4;
19307 n -= 1;
19308 }
19309
19310 return len;
19311}
19312
19313static uint64_t //
19314wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src(
19315 uint8_t* dst_ptr,
19316 size_t dst_len,
19317 uint8_t* dst_palette_ptr,
19318 size_t dst_palette_len,
19319 const uint8_t* src_ptr,
19320 size_t src_len) {
19321 size_t dst_len4 = dst_len / 4;
19322 size_t src_len8 = src_len / 8;
19323 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19324 uint8_t* d = dst_ptr;
19325 const uint8_t* s = src_ptr;
19326 size_t n = len;
19327
19328 // TODO: unroll.
19329
19330 while (n >= 1) {
19331 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
19332 wuffs_base__poke_u32le__no_bounds_check(
19333 d + (0 * 4),
19334 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(s0));
19335
19336 s += 1 * 8;
19337 d += 1 * 4;
19338 n -= 1;
19339 }
19340
19341 return len;
19342}
19343
19344static uint64_t //
19345wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over(
19346 uint8_t* dst_ptr,
19347 size_t dst_len,
19348 uint8_t* dst_palette_ptr,
19349 size_t dst_palette_len,
19350 const uint8_t* src_ptr,
19351 size_t src_len) {
19352 size_t dst_len4 = dst_len / 4;
19353 size_t src_len4 = src_len / 4;
19354 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19355 uint8_t* d = dst_ptr;
19356 const uint8_t* s = src_ptr;
19357 size_t n = len;
19358
19359 // TODO: unroll.
19360
19361 while (n >= 1) {
19362 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
19363 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
19364 wuffs_base__poke_u32le__no_bounds_check(
19365 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
19366
19367 s += 1 * 4;
19368 d += 1 * 4;
19369 n -= 1;
19370 }
19371
19372 return len;
19373}
19374
19375static uint64_t //
19376wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over(
19377 uint8_t* dst_ptr,
19378 size_t dst_len,
19379 uint8_t* dst_palette_ptr,
19380 size_t dst_palette_len,
19381 const uint8_t* src_ptr,
19382 size_t src_len) {
19383 size_t dst_len4 = dst_len / 4;
19384 size_t src_len8 = src_len / 8;
19385 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19386 uint8_t* d = dst_ptr;
19387 const uint8_t* s = src_ptr;
19388 size_t n = len;
19389
19390 // TODO: unroll.
19391
19392 while (n >= 1) {
19393 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
19394 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
19395 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
19396 wuffs_base__poke_u32le__no_bounds_check(
19397 d + (0 * 4),
19398 wuffs_base__color_u64__as__color_u32(
19399 wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0)));
19400
19401 s += 1 * 8;
19402 d += 1 * 4;
19403 n -= 1;
19404 }
19405
19406 return len;
19407}
19408
19409static uint64_t //
19410wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over(
19411 uint8_t* dst_ptr,
19412 size_t dst_len,
19413 uint8_t* dst_palette_ptr,
19414 size_t dst_palette_len,
19415 const uint8_t* src_ptr,
19416 size_t src_len) {
19417 size_t dst_len4 = dst_len / 4;
19418 size_t src_len4 = src_len / 4;
19419 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19420 uint8_t* d = dst_ptr;
19421 const uint8_t* s = src_ptr;
19422 size_t n = len;
19423
19424 // TODO: unroll.
19425
19426 while (n >= 1) {
19427 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
19428 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4));
19429 wuffs_base__poke_u32le__no_bounds_check(
19430 d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0));
19431
19432 s += 1 * 4;
19433 d += 1 * 4;
19434 n -= 1;
19435 }
19436
19437 return len;
19438}
19439
19440static uint64_t //
19441wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over(
19442 uint8_t* dst_ptr,
19443 size_t dst_len,
19444 uint8_t* dst_palette_ptr,
19445 size_t dst_palette_len,
19446 const uint8_t* src_ptr,
19447 size_t src_len) {
19448 if (dst_palette_len !=
19449 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
19450 return 0;
19451 }
19452 size_t dst_len4 = dst_len / 4;
19453 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
19454 uint8_t* d = dst_ptr;
19455 const uint8_t* s = src_ptr;
19456 size_t n = len;
19457
19458 // TODO: unroll.
19459
19460 while (n >= 1) {
19461 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
19462 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
19463 ((size_t)s[0] * 4));
19464 wuffs_base__poke_u32le__no_bounds_check(
19465 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
19466
19467 s += 1 * 1;
19468 d += 1 * 4;
19469 n -= 1;
19470 }
19471
19472 return len;
19473}
19474
19475static uint64_t //
19476wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src(
19477 uint8_t* dst_ptr,
19478 size_t dst_len,
19479 uint8_t* dst_palette_ptr,
19480 size_t dst_palette_len,
19481 const uint8_t* src_ptr,
19482 size_t src_len) {
19483 size_t dst_len4 = dst_len / 4;
19484 size_t src_len4 = src_len / 4;
19485 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19486 uint8_t* d = dst_ptr;
19487 const uint8_t* s = src_ptr;
19488 size_t n = len;
19489
19490 // TODO: unroll.
19491
19492 while (n >= 1) {
19493 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
19494 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19495 wuffs_base__poke_u32le__no_bounds_check(
19496 d + (0 * 4),
19497 wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(s0));
19498
19499 s += 1 * 4;
19500 d += 1 * 4;
19501 n -= 1;
19502 }
19503
19504 return len;
19505}
19506
19507static uint64_t //
19508wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over(
19509 uint8_t* dst_ptr,
19510 size_t dst_len,
19511 uint8_t* dst_palette_ptr,
19512 size_t dst_palette_len,
19513 const uint8_t* src_ptr,
19514 size_t src_len) {
19515 size_t dst_len4 = dst_len / 4;
19516 size_t src_len4 = src_len / 4;
19517 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19518 uint8_t* d = dst_ptr;
19519 const uint8_t* s = src_ptr;
19520 size_t n = len;
19521
19522 // TODO: unroll.
19523
19524 while (n >= 1) {
19525 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
19526 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
19527 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19528 wuffs_base__poke_u32le__no_bounds_check(
19529 d + (0 * 4), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
19530
19531 s += 1 * 4;
19532 d += 1 * 4;
19533 n -= 1;
19534 }
19535
19536 return len;
19537}
19538
19539static uint64_t //
19540wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src(
19541 uint8_t* dst_ptr,
19542 size_t dst_len,
19543 uint8_t* dst_palette_ptr,
19544 size_t dst_palette_len,
19545 const uint8_t* src_ptr,
19546 size_t src_len) {
19547 size_t dst_len4 = dst_len / 4;
19548 size_t src_len8 = src_len / 8;
19549 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19550 uint8_t* d = dst_ptr;
19551 const uint8_t* s = src_ptr;
19552 size_t n = len;
19553
19554 // TODO: unroll.
19555
19556 while (n >= 1) {
19557 uint64_t s0 = wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8));
19558 wuffs_base__poke_u32le__no_bounds_check(
19559 d + (0 * 4),
19560 wuffs_base__swap_u32_argb_abgr(
19561 wuffs_base__color_u64_argb_nonpremul__as__color_u32_argb_premul(
19562 s0)));
19563
19564 s += 1 * 8;
19565 d += 1 * 4;
19566 n -= 1;
19567 }
19568
19569 return len;
19570}
19571
19572static uint64_t //
19573wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over(
19574 uint8_t* dst_ptr,
19575 size_t dst_len,
19576 uint8_t* dst_palette_ptr,
19577 size_t dst_palette_len,
19578 const uint8_t* src_ptr,
19579 size_t src_len) {
19580 size_t dst_len4 = dst_len / 4;
19581 size_t src_len8 = src_len / 8;
19582 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19583 uint8_t* d = dst_ptr;
19584 const uint8_t* s = src_ptr;
19585 size_t n = len;
19586
19587 // TODO: unroll.
19588
19589 while (n >= 1) {
19590 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
19591 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
19592 uint64_t s0 = wuffs_base__swap_u64_argb_abgr(
19593 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
19594 wuffs_base__poke_u32le__no_bounds_check(
19595 d + (0 * 4),
19596 wuffs_base__color_u64__as__color_u32(
19597 wuffs_base__composite_premul_nonpremul_u64_axxx(d0, s0)));
19598
19599 s += 1 * 8;
19600 d += 1 * 4;
19601 n -= 1;
19602 }
19603
19604 return len;
19605}
19606
19607static uint64_t //
19608wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over(
19609 uint8_t* dst_ptr,
19610 size_t dst_len,
19611 uint8_t* dst_palette_ptr,
19612 size_t dst_palette_len,
19613 const uint8_t* src_ptr,
19614 size_t src_len) {
19615 size_t dst_len4 = dst_len / 4;
19616 size_t src_len4 = src_len / 4;
19617 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19618 uint8_t* d = dst_ptr;
19619 const uint8_t* s = src_ptr;
19620 size_t n = len;
19621
19622 while (n >= 1) {
19623 uint32_t d0 = wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4));
19624 uint32_t s0 = wuffs_base__swap_u32_argb_abgr(
19625 wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19626 wuffs_base__poke_u32le__no_bounds_check(
19627 d + (0 * 4), wuffs_base__composite_premul_premul_u32_axxx(d0, s0));
19628
19629 s += 1 * 4;
19630 d += 1 * 4;
19631 n -= 1;
19632 }
19633
19634 return len;
19635}
19636
19637// --------
19638
19639static uint64_t //
19640wuffs_base__pixel_swizzler__bgrw__bgr(uint8_t* dst_ptr,
19641 size_t dst_len,
19642 uint8_t* dst_palette_ptr,
19643 size_t dst_palette_len,
19644 const uint8_t* src_ptr,
19645 size_t src_len) {
19646 size_t dst_len4 = dst_len / 4;
19647 size_t src_len3 = src_len / 3;
19648 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
19649 uint8_t* d = dst_ptr;
19650 const uint8_t* s = src_ptr;
19651 size_t n = len;
19652
19653 // TODO: unroll.
19654
19655 while (n >= 1) {
19656 wuffs_base__poke_u32le__no_bounds_check(
19657 d + (0 * 4),
19658 0xFF000000 | wuffs_base__peek_u24le__no_bounds_check(s + (0 * 3)));
19659
19660 s += 1 * 3;
19661 d += 1 * 4;
19662 n -= 1;
19663 }
19664
19665 return len;
19666}
19667
19668static uint64_t //
19669wuffs_base__pixel_swizzler__bgrw__bgr_565(uint8_t* dst_ptr,
19670 size_t dst_len,
19671 uint8_t* dst_palette_ptr,
19672 size_t dst_palette_len,
19673 const uint8_t* src_ptr,
19674 size_t src_len) {
19675 size_t dst_len4 = dst_len / 4;
19676 size_t src_len2 = src_len / 2;
19677 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
19678 uint8_t* d = dst_ptr;
19679 const uint8_t* s = src_ptr;
19680 size_t n = len;
19681
19682 // TODO: unroll.
19683
19684 while (n >= 1) {
19685 wuffs_base__poke_u32le__no_bounds_check(
19686 d + (0 * 4), wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
19687 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2))));
19688
19689 s += 1 * 2;
19690 d += 1 * 4;
19691 n -= 1;
19692 }
19693
19694 return len;
19695}
19696
19697static uint64_t //
19698wuffs_base__pixel_swizzler__bgrw__bgrx(uint8_t* dst_ptr,
19699 size_t dst_len,
19700 uint8_t* dst_palette_ptr,
19701 size_t dst_palette_len,
19702 const uint8_t* src_ptr,
19703 size_t src_len) {
19704 size_t dst_len4 = dst_len / 4;
19705 size_t src_len4 = src_len / 4;
19706 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19707 uint8_t* d = dst_ptr;
19708 const uint8_t* s = src_ptr;
19709 size_t n = len;
19710
19711 // TODO: unroll.
19712
19713 while (n >= 1) {
19714 wuffs_base__poke_u32le__no_bounds_check(
19715 d + (0 * 4),
19716 0xFF000000 | wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
19717
19718 s += 1 * 4;
19719 d += 1 * 4;
19720 n -= 1;
19721 }
19722
19723 return len;
19724}
19725
19726// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110019727#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100019728WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
19729static uint64_t //
19730wuffs_base__pixel_swizzler__bgrw__rgb__sse42(uint8_t* dst_ptr,
19731 size_t dst_len,
19732 uint8_t* dst_palette_ptr,
19733 size_t dst_palette_len,
19734 const uint8_t* src_ptr,
19735 size_t src_len) {
19736 size_t dst_len4 = dst_len / 4;
19737 size_t src_len3 = src_len / 3;
19738 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
19739 uint8_t* d = dst_ptr;
19740 const uint8_t* s = src_ptr;
19741 size_t n = len;
19742
19743 __m128i shuffle = _mm_set_epi8(+0x00, +0x09, +0x0A, +0x0B, //
19744 +0x00, +0x06, +0x07, +0x08, //
19745 +0x00, +0x03, +0x04, +0x05, //
19746 +0x00, +0x00, +0x01, +0x02);
19747 __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, //
19748 -0x01, +0x00, +0x00, +0x00, //
19749 -0x01, +0x00, +0x00, +0x00, //
19750 -0x01, +0x00, +0x00, +0x00);
19751
19752 while (n >= 6) {
19753 __m128i x;
19754 x = _mm_lddqu_si128((const __m128i*)(const void*)s);
19755 x = _mm_shuffle_epi8(x, shuffle);
19756 x = _mm_or_si128(x, or_ff);
19757 _mm_storeu_si128((__m128i*)(void*)d, x);
19758
19759 s += 4 * 3;
19760 d += 4 * 4;
19761 n -= 4;
19762 }
19763
19764 while (n >= 1) {
19765 uint8_t b0 = s[0];
19766 uint8_t b1 = s[1];
19767 uint8_t b2 = s[2];
19768 d[0] = b2;
19769 d[1] = b1;
19770 d[2] = b0;
19771 d[3] = 0xFF;
19772
19773 s += 1 * 3;
19774 d += 1 * 4;
19775 n -= 1;
19776 }
19777
19778 return len;
19779}
Nigel Tao7804ffe2021-10-07 21:58:26 +110019780#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100019781// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
19782
19783static uint64_t //
19784wuffs_base__pixel_swizzler__bgrw__rgb(uint8_t* dst_ptr,
19785 size_t dst_len,
19786 uint8_t* dst_palette_ptr,
19787 size_t dst_palette_len,
19788 const uint8_t* src_ptr,
19789 size_t src_len) {
19790 size_t dst_len4 = dst_len / 4;
19791 size_t src_len3 = src_len / 3;
19792 size_t len = (dst_len4 < src_len3) ? dst_len4 : src_len3;
19793 uint8_t* d = dst_ptr;
19794 const uint8_t* s = src_ptr;
19795 size_t n = len;
19796
19797 while (n >= 1) {
19798 uint8_t b0 = s[0];
19799 uint8_t b1 = s[1];
19800 uint8_t b2 = s[2];
19801 d[0] = b2;
19802 d[1] = b1;
19803 d[2] = b0;
19804 d[3] = 0xFF;
19805
19806 s += 1 * 3;
19807 d += 1 * 4;
19808 n -= 1;
19809 }
19810
19811 return len;
19812}
19813
19814static uint64_t //
19815wuffs_base__pixel_swizzler__bgrw__rgbx(uint8_t* dst_ptr,
19816 size_t dst_len,
19817 uint8_t* dst_palette_ptr,
19818 size_t dst_palette_len,
19819 const uint8_t* src_ptr,
19820 size_t src_len) {
19821 size_t dst_len4 = dst_len / 4;
19822 size_t src_len4 = src_len / 4;
19823 size_t len = (dst_len4 < src_len4) ? dst_len4 : src_len4;
19824 uint8_t* d = dst_ptr;
19825 const uint8_t* s = src_ptr;
19826 size_t n = len;
19827
19828 // TODO: unroll.
19829
19830 while (n >= 1) {
19831 uint8_t b0 = s[0];
19832 uint8_t b1 = s[1];
19833 uint8_t b2 = s[2];
19834 d[0] = b2;
19835 d[1] = b1;
19836 d[2] = b0;
19837 d[3] = 0xFF;
19838
19839 s += 1 * 4;
19840 d += 1 * 4;
19841 n -= 1;
19842 }
19843
19844 return len;
19845}
19846
19847// --------
19848
19849static uint64_t //
19850wuffs_base__pixel_swizzler__bgrw_4x16le__bgr(uint8_t* dst_ptr,
19851 size_t dst_len,
19852 uint8_t* dst_palette_ptr,
19853 size_t dst_palette_len,
19854 const uint8_t* src_ptr,
19855 size_t src_len) {
19856 size_t dst_len8 = dst_len / 8;
19857 size_t src_len3 = src_len / 3;
19858 size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3;
19859 uint8_t* d = dst_ptr;
19860 const uint8_t* s = src_ptr;
19861 size_t n = len;
19862
19863 while (n >= 1) {
19864 uint8_t s0 = s[0];
19865 uint8_t s1 = s[1];
19866 uint8_t s2 = s[2];
19867 d[0] = s0;
19868 d[1] = s0;
19869 d[2] = s1;
19870 d[3] = s1;
19871 d[4] = s2;
19872 d[5] = s2;
19873 d[6] = 0xFF;
19874 d[7] = 0xFF;
19875
19876 s += 1 * 3;
19877 d += 1 * 8;
19878 n -= 1;
19879 }
19880
19881 return len;
19882}
19883
19884static uint64_t //
19885wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565(uint8_t* dst_ptr,
19886 size_t dst_len,
19887 uint8_t* dst_palette_ptr,
19888 size_t dst_palette_len,
19889 const uint8_t* src_ptr,
19890 size_t src_len) {
19891 size_t dst_len8 = dst_len / 8;
19892 size_t src_len2 = src_len / 2;
19893 size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2;
19894 uint8_t* d = dst_ptr;
19895 const uint8_t* s = src_ptr;
19896 size_t n = len;
19897
19898 while (n >= 1) {
19899 wuffs_base__poke_u64le__no_bounds_check(
19900 d + (0 * 8),
19901 wuffs_base__color_u32__as__color_u64(
19902 wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
19903 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))));
19904
19905 s += 1 * 2;
19906 d += 1 * 8;
19907 n -= 1;
19908 }
19909
19910 return len;
19911}
19912
19913static uint64_t //
19914wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx(uint8_t* dst_ptr,
19915 size_t dst_len,
19916 uint8_t* dst_palette_ptr,
19917 size_t dst_palette_len,
19918 const uint8_t* src_ptr,
19919 size_t src_len) {
19920 size_t dst_len8 = dst_len / 8;
19921 size_t src_len4 = src_len / 4;
19922 size_t len = (dst_len8 < src_len4) ? dst_len8 : src_len4;
19923 uint8_t* d = dst_ptr;
19924 const uint8_t* s = src_ptr;
19925 size_t n = len;
19926
19927 while (n >= 1) {
19928 uint8_t s0 = s[0];
19929 uint8_t s1 = s[1];
19930 uint8_t s2 = s[2];
19931 d[0] = s0;
19932 d[1] = s0;
19933 d[2] = s1;
19934 d[3] = s1;
19935 d[4] = s2;
19936 d[5] = s2;
19937 d[6] = 0xFF;
19938 d[7] = 0xFF;
19939
19940 s += 1 * 4;
19941 d += 1 * 8;
19942 n -= 1;
19943 }
19944
19945 return len;
19946}
19947
19948static uint64_t //
19949wuffs_base__pixel_swizzler__bgrw_4x16le__rgb(uint8_t* dst_ptr,
19950 size_t dst_len,
19951 uint8_t* dst_palette_ptr,
19952 size_t dst_palette_len,
19953 const uint8_t* src_ptr,
19954 size_t src_len) {
19955 size_t dst_len8 = dst_len / 8;
19956 size_t src_len3 = src_len / 3;
19957 size_t len = (dst_len8 < src_len3) ? dst_len8 : src_len3;
19958 uint8_t* d = dst_ptr;
19959 const uint8_t* s = src_ptr;
19960 size_t n = len;
19961
19962 while (n >= 1) {
19963 uint8_t s0 = s[0];
19964 uint8_t s1 = s[1];
19965 uint8_t s2 = s[2];
19966 d[0] = s2;
19967 d[1] = s2;
19968 d[2] = s1;
19969 d[3] = s1;
19970 d[4] = s0;
19971 d[5] = s0;
19972 d[6] = 0xFF;
19973 d[7] = 0xFF;
19974
19975 s += 1 * 3;
19976 d += 1 * 8;
19977 n -= 1;
19978 }
19979
19980 return len;
19981}
19982
19983// --------
19984
19985static uint64_t //
19986wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src(
19987 uint8_t* dst_ptr,
19988 size_t dst_len,
19989 uint8_t* dst_palette_ptr,
19990 size_t dst_palette_len,
19991 const uint8_t* src_ptr,
19992 size_t src_len) {
19993 size_t dst_len4 = dst_len / 4;
19994 size_t src_len8 = src_len / 8;
19995 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
19996 uint8_t* d = dst_ptr;
19997 const uint8_t* s = src_ptr;
19998
19999 size_t n = len;
20000 while (n >= 1) {
20001 wuffs_base__poke_u32le__no_bounds_check(
20002 d + (0 * 4), wuffs_base__color_u64__as__color_u32__swap_u32_argb_abgr(
20003 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8))));
20004
20005 s += 1 * 8;
20006 d += 1 * 4;
20007 n -= 1;
20008 }
20009 return len;
20010}
20011
20012static uint64_t //
20013wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over(
20014 uint8_t* dst_ptr,
20015 size_t dst_len,
20016 uint8_t* dst_palette_ptr,
20017 size_t dst_palette_len,
20018 const uint8_t* src_ptr,
20019 size_t src_len) {
20020 size_t dst_len4 = dst_len / 4;
20021 size_t src_len8 = src_len / 8;
20022 size_t len = (dst_len4 < src_len8) ? dst_len4 : src_len8;
20023 uint8_t* d = dst_ptr;
20024 const uint8_t* s = src_ptr;
20025 size_t n = len;
20026
20027 while (n >= 1) {
20028 uint64_t d0 = wuffs_base__color_u32__as__color_u64(
20029 wuffs_base__peek_u32le__no_bounds_check(d + (0 * 4)));
20030 uint64_t s0 = wuffs_base__swap_u64_argb_abgr(
20031 wuffs_base__peek_u64le__no_bounds_check(s + (0 * 8)));
20032 wuffs_base__poke_u32le__no_bounds_check(
20033 d + (0 * 4),
20034 wuffs_base__color_u64__as__color_u32(
20035 wuffs_base__composite_nonpremul_nonpremul_u64_axxx(d0, s0)));
20036
20037 s += 1 * 8;
20038 d += 1 * 4;
20039 n -= 1;
20040 }
20041
20042 return len;
20043}
20044
20045// --------
20046
20047static uint64_t //
20048wuffs_base__pixel_swizzler__rgbw__bgr_565(uint8_t* dst_ptr,
20049 size_t dst_len,
20050 uint8_t* dst_palette_ptr,
20051 size_t dst_palette_len,
20052 const uint8_t* src_ptr,
20053 size_t src_len) {
20054 size_t dst_len4 = dst_len / 4;
20055 size_t src_len2 = src_len / 2;
20056 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
20057 uint8_t* d = dst_ptr;
20058 const uint8_t* s = src_ptr;
20059 size_t n = len;
20060
20061 // TODO: unroll.
20062
20063 while (n >= 1) {
20064 wuffs_base__poke_u32le__no_bounds_check(
20065 d + (0 * 4),
20066 wuffs_base__swap_u32_argb_abgr(
20067 wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
20068 wuffs_base__peek_u16le__no_bounds_check(s + (0 * 2)))));
20069
20070 s += 1 * 2;
20071 d += 1 * 4;
20072 n -= 1;
20073 }
20074
20075 return len;
20076}
20077
20078// --------
20079
20080static uint64_t //
20081wuffs_base__pixel_swizzler__xxx__index__src(uint8_t* dst_ptr,
20082 size_t dst_len,
20083 uint8_t* dst_palette_ptr,
20084 size_t dst_palette_len,
20085 const uint8_t* src_ptr,
20086 size_t src_len) {
20087 if (dst_palette_len !=
20088 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20089 return 0;
20090 }
20091 size_t dst_len3 = dst_len / 3;
20092 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
20093 uint8_t* d = dst_ptr;
20094 const uint8_t* s = src_ptr;
20095 size_t n = len;
20096
20097 const size_t loop_unroll_count = 4;
20098
20099 // The comparison in the while condition is ">", not ">=", because with
20100 // ">=", the last 4-byte store could write past the end of the dst slice.
20101 //
20102 // Each 4-byte store writes one too many bytes, but a subsequent store
20103 // will overwrite that with the correct byte. There is always another
20104 // store, whether a 4-byte store in this loop or a 1-byte store in the
20105 // next loop.
20106 while (n > loop_unroll_count) {
20107 wuffs_base__poke_u32le__no_bounds_check(
20108 d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(
20109 dst_palette_ptr + ((size_t)s[0] * 4)));
20110 wuffs_base__poke_u32le__no_bounds_check(
20111 d + (1 * 3), wuffs_base__peek_u32le__no_bounds_check(
20112 dst_palette_ptr + ((size_t)s[1] * 4)));
20113 wuffs_base__poke_u32le__no_bounds_check(
20114 d + (2 * 3), wuffs_base__peek_u32le__no_bounds_check(
20115 dst_palette_ptr + ((size_t)s[2] * 4)));
20116 wuffs_base__poke_u32le__no_bounds_check(
20117 d + (3 * 3), wuffs_base__peek_u32le__no_bounds_check(
20118 dst_palette_ptr + ((size_t)s[3] * 4)));
20119
20120 s += loop_unroll_count * 1;
20121 d += loop_unroll_count * 3;
20122 n -= loop_unroll_count;
20123 }
20124
20125 while (n >= 1) {
20126 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20127 ((size_t)s[0] * 4));
20128 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
20129
20130 s += 1 * 1;
20131 d += 1 * 3;
20132 n -= 1;
20133 }
20134
20135 return len;
20136}
20137
20138static uint64_t //
20139wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over(
20140 uint8_t* dst_ptr,
20141 size_t dst_len,
20142 uint8_t* dst_palette_ptr,
20143 size_t dst_palette_len,
20144 const uint8_t* src_ptr,
20145 size_t src_len) {
20146 if (dst_palette_len !=
20147 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20148 return 0;
20149 }
20150 size_t dst_len3 = dst_len / 3;
20151 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
20152 uint8_t* d = dst_ptr;
20153 const uint8_t* s = src_ptr;
20154 size_t n = len;
20155
20156 // TODO: unroll.
20157
20158 while (n >= 1) {
20159 uint32_t d0 =
20160 wuffs_base__peek_u24le__no_bounds_check(d + (0 * 3)) | 0xFF000000;
20161 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20162 ((size_t)s[0] * 4));
20163 wuffs_base__poke_u24le__no_bounds_check(
20164 d + (0 * 3), wuffs_base__composite_premul_nonpremul_u32_axxx(d0, s0));
20165
20166 s += 1 * 1;
20167 d += 1 * 3;
20168 n -= 1;
20169 }
20170
20171 return len;
20172}
20173
20174static uint64_t //
20175wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over(
20176 uint8_t* dst_ptr,
20177 size_t dst_len,
20178 uint8_t* dst_palette_ptr,
20179 size_t dst_palette_len,
20180 const uint8_t* src_ptr,
20181 size_t src_len) {
20182 if (dst_palette_len !=
20183 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20184 return 0;
20185 }
20186 size_t dst_len3 = dst_len / 3;
20187 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
20188 uint8_t* d = dst_ptr;
20189 const uint8_t* s = src_ptr;
20190 size_t n = len;
20191
20192 const size_t loop_unroll_count = 4;
20193
20194 while (n >= loop_unroll_count) {
20195 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20196 ((size_t)s[0] * 4));
20197 if (s0) {
20198 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
20199 }
20200 uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20201 ((size_t)s[1] * 4));
20202 if (s1) {
20203 wuffs_base__poke_u24le__no_bounds_check(d + (1 * 3), s1);
20204 }
20205 uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20206 ((size_t)s[2] * 4));
20207 if (s2) {
20208 wuffs_base__poke_u24le__no_bounds_check(d + (2 * 3), s2);
20209 }
20210 uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20211 ((size_t)s[3] * 4));
20212 if (s3) {
20213 wuffs_base__poke_u24le__no_bounds_check(d + (3 * 3), s3);
20214 }
20215
20216 s += loop_unroll_count * 1;
20217 d += loop_unroll_count * 3;
20218 n -= loop_unroll_count;
20219 }
20220
20221 while (n >= 1) {
20222 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20223 ((size_t)s[0] * 4));
20224 if (s0) {
20225 wuffs_base__poke_u24le__no_bounds_check(d + (0 * 3), s0);
20226 }
20227
20228 s += 1 * 1;
20229 d += 1 * 3;
20230 n -= 1;
20231 }
20232
20233 return len;
20234}
20235
20236static uint64_t //
20237wuffs_base__pixel_swizzler__xxx__xxxx(uint8_t* dst_ptr,
20238 size_t dst_len,
20239 uint8_t* dst_palette_ptr,
20240 size_t dst_palette_len,
20241 const uint8_t* src_ptr,
20242 size_t src_len) {
20243 size_t dst_len3 = dst_len / 3;
20244 size_t src_len4 = src_len / 4;
20245 size_t len = (dst_len3 < src_len4) ? dst_len3 : src_len4;
20246 uint8_t* d = dst_ptr;
20247 const uint8_t* s = src_ptr;
20248 size_t n = len;
20249
20250 // TODO: unroll.
20251
20252 while (n >= 1) {
20253 wuffs_base__poke_u24le__no_bounds_check(
20254 d + (0 * 3), wuffs_base__peek_u32le__no_bounds_check(s + (0 * 4)));
20255
20256 s += 1 * 4;
20257 d += 1 * 3;
20258 n -= 1;
20259 }
20260
20261 return len;
20262}
20263
20264static uint64_t //
20265wuffs_base__pixel_swizzler__xxx__y(uint8_t* dst_ptr,
20266 size_t dst_len,
20267 uint8_t* dst_palette_ptr,
20268 size_t dst_palette_len,
20269 const uint8_t* src_ptr,
20270 size_t src_len) {
20271 size_t dst_len3 = dst_len / 3;
20272 size_t len = (dst_len3 < src_len) ? dst_len3 : src_len;
20273 uint8_t* d = dst_ptr;
20274 const uint8_t* s = src_ptr;
20275 size_t n = len;
20276
20277 // TODO: unroll.
20278
20279 while (n >= 1) {
20280 uint8_t s0 = s[0];
20281 d[0] = s0;
20282 d[1] = s0;
20283 d[2] = s0;
20284
20285 s += 1 * 1;
20286 d += 1 * 3;
20287 n -= 1;
20288 }
20289
20290 return len;
20291}
20292
20293static uint64_t //
20294wuffs_base__pixel_swizzler__xxx__y_16be(uint8_t* dst_ptr,
20295 size_t dst_len,
20296 uint8_t* dst_palette_ptr,
20297 size_t dst_palette_len,
20298 const uint8_t* src_ptr,
20299 size_t src_len) {
20300 size_t dst_len3 = dst_len / 3;
20301 size_t src_len2 = src_len / 2;
20302 size_t len = (dst_len3 < src_len2) ? dst_len3 : src_len2;
20303 uint8_t* d = dst_ptr;
20304 const uint8_t* s = src_ptr;
20305 size_t n = len;
20306
20307 // TODO: unroll.
20308
20309 while (n >= 1) {
20310 uint8_t s0 = s[0];
20311 d[0] = s0;
20312 d[1] = s0;
20313 d[2] = s0;
20314
20315 s += 1 * 2;
20316 d += 1 * 3;
20317 n -= 1;
20318 }
20319
20320 return len;
20321}
20322
20323// --------
20324
20325static uint64_t //
20326wuffs_base__pixel_swizzler__xxxx__index__src(uint8_t* dst_ptr,
20327 size_t dst_len,
20328 uint8_t* dst_palette_ptr,
20329 size_t dst_palette_len,
20330 const uint8_t* src_ptr,
20331 size_t src_len) {
20332 if (dst_palette_len !=
20333 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20334 return 0;
20335 }
20336 size_t dst_len4 = dst_len / 4;
20337 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
20338 uint8_t* d = dst_ptr;
20339 const uint8_t* s = src_ptr;
20340 size_t n = len;
20341
20342 const size_t loop_unroll_count = 4;
20343
20344 while (n >= loop_unroll_count) {
20345 wuffs_base__poke_u32le__no_bounds_check(
20346 d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check(
20347 dst_palette_ptr + ((size_t)s[0] * 4)));
20348 wuffs_base__poke_u32le__no_bounds_check(
20349 d + (1 * 4), wuffs_base__peek_u32le__no_bounds_check(
20350 dst_palette_ptr + ((size_t)s[1] * 4)));
20351 wuffs_base__poke_u32le__no_bounds_check(
20352 d + (2 * 4), wuffs_base__peek_u32le__no_bounds_check(
20353 dst_palette_ptr + ((size_t)s[2] * 4)));
20354 wuffs_base__poke_u32le__no_bounds_check(
20355 d + (3 * 4), wuffs_base__peek_u32le__no_bounds_check(
20356 dst_palette_ptr + ((size_t)s[3] * 4)));
20357
20358 s += loop_unroll_count * 1;
20359 d += loop_unroll_count * 4;
20360 n -= loop_unroll_count;
20361 }
20362
20363 while (n >= 1) {
20364 wuffs_base__poke_u32le__no_bounds_check(
20365 d + (0 * 4), wuffs_base__peek_u32le__no_bounds_check(
20366 dst_palette_ptr + ((size_t)s[0] * 4)));
20367
20368 s += 1 * 1;
20369 d += 1 * 4;
20370 n -= 1;
20371 }
20372
20373 return len;
20374}
20375
20376static uint64_t //
20377wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over(
20378 uint8_t* dst_ptr,
20379 size_t dst_len,
20380 uint8_t* dst_palette_ptr,
20381 size_t dst_palette_len,
20382 const uint8_t* src_ptr,
20383 size_t src_len) {
20384 if (dst_palette_len !=
20385 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20386 return 0;
20387 }
20388 size_t dst_len4 = dst_len / 4;
20389 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
20390 uint8_t* d = dst_ptr;
20391 const uint8_t* s = src_ptr;
20392 size_t n = len;
20393
20394 const size_t loop_unroll_count = 4;
20395
20396 while (n >= loop_unroll_count) {
20397 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20398 ((size_t)s[0] * 4));
20399 if (s0) {
20400 wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0);
20401 }
20402 uint32_t s1 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20403 ((size_t)s[1] * 4));
20404 if (s1) {
20405 wuffs_base__poke_u32le__no_bounds_check(d + (1 * 4), s1);
20406 }
20407 uint32_t s2 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20408 ((size_t)s[2] * 4));
20409 if (s2) {
20410 wuffs_base__poke_u32le__no_bounds_check(d + (2 * 4), s2);
20411 }
20412 uint32_t s3 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20413 ((size_t)s[3] * 4));
20414 if (s3) {
20415 wuffs_base__poke_u32le__no_bounds_check(d + (3 * 4), s3);
20416 }
20417
20418 s += loop_unroll_count * 1;
20419 d += loop_unroll_count * 4;
20420 n -= loop_unroll_count;
20421 }
20422
20423 while (n >= 1) {
20424 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20425 ((size_t)s[0] * 4));
20426 if (s0) {
20427 wuffs_base__poke_u32le__no_bounds_check(d + (0 * 4), s0);
20428 }
20429
20430 s += 1 * 1;
20431 d += 1 * 4;
20432 n -= 1;
20433 }
20434
20435 return len;
20436}
20437
20438// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
Nigel Tao7804ffe2021-10-07 21:58:26 +110020439#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020440WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
20441static uint64_t //
20442wuffs_base__pixel_swizzler__xxxx__y__sse42(uint8_t* dst_ptr,
20443 size_t dst_len,
20444 uint8_t* dst_palette_ptr,
20445 size_t dst_palette_len,
20446 const uint8_t* src_ptr,
20447 size_t src_len) {
20448 size_t dst_len4 = dst_len / 4;
20449 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
20450 uint8_t* d = dst_ptr;
20451 const uint8_t* s = src_ptr;
20452 size_t n = len;
20453
20454 __m128i shuffle = _mm_set_epi8(+0x03, +0x03, +0x03, +0x03, //
20455 +0x02, +0x02, +0x02, +0x02, //
20456 +0x01, +0x01, +0x01, +0x01, //
20457 +0x00, +0x00, +0x00, +0x00);
20458 __m128i or_ff = _mm_set_epi8(-0x01, +0x00, +0x00, +0x00, //
20459 -0x01, +0x00, +0x00, +0x00, //
20460 -0x01, +0x00, +0x00, +0x00, //
20461 -0x01, +0x00, +0x00, +0x00);
20462
20463 while (n >= 4) {
20464 __m128i x;
20465 x = _mm_cvtsi32_si128((int)(wuffs_base__peek_u32le__no_bounds_check(s)));
20466 x = _mm_shuffle_epi8(x, shuffle);
20467 x = _mm_or_si128(x, or_ff);
20468 _mm_storeu_si128((__m128i*)(void*)d, x);
20469
20470 s += 4 * 1;
20471 d += 4 * 4;
20472 n -= 4;
20473 }
20474
20475 while (n >= 1) {
20476 wuffs_base__poke_u32le__no_bounds_check(
20477 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
20478
20479 s += 1 * 1;
20480 d += 1 * 4;
20481 n -= 1;
20482 }
20483
20484 return len;
20485}
Nigel Tao7804ffe2021-10-07 21:58:26 +110020486#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020487// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
20488
20489static uint64_t //
20490wuffs_base__pixel_swizzler__xxxx__y(uint8_t* dst_ptr,
20491 size_t dst_len,
20492 uint8_t* dst_palette_ptr,
20493 size_t dst_palette_len,
20494 const uint8_t* src_ptr,
20495 size_t src_len) {
20496 size_t dst_len4 = dst_len / 4;
20497 size_t len = (dst_len4 < src_len) ? dst_len4 : src_len;
20498 uint8_t* d = dst_ptr;
20499 const uint8_t* s = src_ptr;
20500 size_t n = len;
20501
20502 while (n >= 1) {
20503 wuffs_base__poke_u32le__no_bounds_check(
20504 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
20505
20506 s += 1 * 1;
20507 d += 1 * 4;
20508 n -= 1;
20509 }
20510
20511 return len;
20512}
20513
20514static uint64_t //
20515wuffs_base__pixel_swizzler__xxxx__y_16be(uint8_t* dst_ptr,
20516 size_t dst_len,
20517 uint8_t* dst_palette_ptr,
20518 size_t dst_palette_len,
20519 const uint8_t* src_ptr,
20520 size_t src_len) {
20521 size_t dst_len4 = dst_len / 4;
20522 size_t src_len2 = src_len / 2;
20523 size_t len = (dst_len4 < src_len2) ? dst_len4 : src_len2;
20524 uint8_t* d = dst_ptr;
20525 const uint8_t* s = src_ptr;
20526 size_t n = len;
20527
20528 while (n >= 1) {
20529 wuffs_base__poke_u32le__no_bounds_check(
20530 d + (0 * 4), 0xFF000000 | (0x010101 * (uint32_t)s[0]));
20531
20532 s += 1 * 2;
20533 d += 1 * 4;
20534 n -= 1;
20535 }
20536
20537 return len;
20538}
20539
20540// --------
20541
20542static uint64_t //
20543wuffs_base__pixel_swizzler__xxxxxxxx__index__src(uint8_t* dst_ptr,
20544 size_t dst_len,
20545 uint8_t* dst_palette_ptr,
20546 size_t dst_palette_len,
20547 const uint8_t* src_ptr,
20548 size_t src_len) {
20549 if (dst_palette_len !=
20550 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20551 return 0;
20552 }
20553 size_t dst_len8 = dst_len / 8;
20554 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
20555 uint8_t* d = dst_ptr;
20556 const uint8_t* s = src_ptr;
20557 size_t n = len;
20558
20559 while (n >= 1) {
20560 wuffs_base__poke_u64le__no_bounds_check(
20561 d + (0 * 8), wuffs_base__color_u32__as__color_u64(
20562 wuffs_base__peek_u32le__no_bounds_check(
20563 dst_palette_ptr + ((size_t)s[0] * 4))));
20564
20565 s += 1 * 1;
20566 d += 1 * 8;
20567 n -= 1;
20568 }
20569
20570 return len;
20571}
20572
20573static uint64_t //
20574wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over(
20575 uint8_t* dst_ptr,
20576 size_t dst_len,
20577 uint8_t* dst_palette_ptr,
20578 size_t dst_palette_len,
20579 const uint8_t* src_ptr,
20580 size_t src_len) {
20581 if (dst_palette_len !=
20582 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20583 return 0;
20584 }
20585 size_t dst_len8 = dst_len / 8;
20586 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
20587 uint8_t* d = dst_ptr;
20588 const uint8_t* s = src_ptr;
20589 size_t n = len;
20590
20591 while (n >= 1) {
20592 uint32_t s0 = wuffs_base__peek_u32le__no_bounds_check(dst_palette_ptr +
20593 ((size_t)s[0] * 4));
20594 if (s0) {
20595 wuffs_base__poke_u64le__no_bounds_check(
20596 d + (0 * 8), wuffs_base__color_u32__as__color_u64(s0));
20597 }
20598
20599 s += 1 * 1;
20600 d += 1 * 8;
20601 n -= 1;
20602 }
20603
20604 return len;
20605}
20606
20607static uint64_t //
20608wuffs_base__pixel_swizzler__xxxxxxxx__y(uint8_t* dst_ptr,
20609 size_t dst_len,
20610 uint8_t* dst_palette_ptr,
20611 size_t dst_palette_len,
20612 const uint8_t* src_ptr,
20613 size_t src_len) {
20614 size_t dst_len8 = dst_len / 8;
20615 size_t len = (dst_len8 < src_len) ? dst_len8 : src_len;
20616 uint8_t* d = dst_ptr;
20617 const uint8_t* s = src_ptr;
20618 size_t n = len;
20619
20620 while (n >= 1) {
20621 wuffs_base__poke_u64le__no_bounds_check(
20622 d + (0 * 8), 0xFFFF000000000000 | (0x010101010101 * (uint64_t)s[0]));
20623
20624 s += 1 * 1;
20625 d += 1 * 8;
20626 n -= 1;
20627 }
20628
20629 return len;
20630}
20631
20632static uint64_t //
20633wuffs_base__pixel_swizzler__xxxxxxxx__y_16be(uint8_t* dst_ptr,
20634 size_t dst_len,
20635 uint8_t* dst_palette_ptr,
20636 size_t dst_palette_len,
20637 const uint8_t* src_ptr,
20638 size_t src_len) {
20639 size_t dst_len8 = dst_len / 8;
20640 size_t src_len2 = src_len / 2;
20641 size_t len = (dst_len8 < src_len2) ? dst_len8 : src_len2;
20642 uint8_t* d = dst_ptr;
20643 const uint8_t* s = src_ptr;
20644 size_t n = len;
20645
20646 while (n >= 1) {
20647 uint64_t s0 =
20648 ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(s + (0 * 2))));
20649 wuffs_base__poke_u64le__no_bounds_check(
20650 d + (0 * 8), 0xFFFF000000000000 | (0x000100010001 * s0));
20651
20652 s += 1 * 2;
20653 d += 1 * 8;
20654 n -= 1;
20655 }
20656
20657 return len;
20658}
20659
20660// --------
20661
20662static uint64_t //
20663wuffs_base__pixel_swizzler__y__y_16be(uint8_t* dst_ptr,
20664 size_t dst_len,
20665 uint8_t* dst_palette_ptr,
20666 size_t dst_palette_len,
20667 const uint8_t* src_ptr,
20668 size_t src_len) {
20669 size_t src_len2 = src_len / 2;
20670 size_t len = (dst_len < src_len2) ? dst_len : src_len2;
20671 uint8_t* d = dst_ptr;
20672 const uint8_t* s = src_ptr;
20673 size_t n = len;
20674
20675 while (n >= 1) {
20676 d[0] = s[0];
20677
20678 s += 1 * 2;
20679 d += 1 * 1;
20680 n -= 1;
20681 }
20682
20683 return len;
20684}
20685
Nigel Tao5571bfe2021-06-24 22:44:29 +100020686static uint64_t //
20687wuffs_base__pixel_swizzler__y_16le__y_16be(uint8_t* dst_ptr,
20688 size_t dst_len,
20689 uint8_t* dst_palette_ptr,
20690 size_t dst_palette_len,
20691 const uint8_t* src_ptr,
20692 size_t src_len) {
20693 size_t dst_len2 = dst_len / 2;
20694 size_t src_len2 = src_len / 2;
20695 size_t len = (dst_len2 < src_len2) ? dst_len2 : src_len2;
20696 uint8_t* d = dst_ptr;
20697 const uint8_t* s = src_ptr;
20698 size_t n = len;
20699
20700 while (n >= 1) {
20701 uint8_t s0 = s[0];
20702 uint8_t s1 = s[1];
20703 d[0] = s1;
20704 d[1] = s0;
20705
20706 s += 1 * 2;
20707 d += 1 * 2;
20708 n -= 1;
20709 }
20710
20711 return len;
20712}
20713
Nigel Taoe360a532021-04-05 22:47:03 +100020714// --------
20715
20716static uint64_t //
20717wuffs_base__pixel_swizzler__transparent_black_src(
20718 uint8_t* dst_ptr,
20719 size_t dst_len,
20720 uint8_t* dst_palette_ptr,
20721 size_t dst_palette_len,
20722 uint64_t num_pixels,
20723 uint32_t dst_pixfmt_bytes_per_pixel) {
20724 uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel;
20725 if (n > num_pixels) {
20726 n = num_pixels;
20727 }
20728 memset(dst_ptr, 0, ((size_t)(n * dst_pixfmt_bytes_per_pixel)));
20729 return n;
20730}
20731
20732static uint64_t //
20733wuffs_base__pixel_swizzler__transparent_black_src_over(
20734 uint8_t* dst_ptr,
20735 size_t dst_len,
20736 uint8_t* dst_palette_ptr,
20737 size_t dst_palette_len,
20738 uint64_t num_pixels,
20739 uint32_t dst_pixfmt_bytes_per_pixel) {
20740 uint64_t n = ((uint64_t)dst_len) / dst_pixfmt_bytes_per_pixel;
20741 if (n > num_pixels) {
20742 n = num_pixels;
20743 }
20744 return n;
20745}
20746
20747// --------
20748
20749static wuffs_base__pixel_swizzler__func //
20750wuffs_base__pixel_swizzler__prepare__y(wuffs_base__pixel_swizzler* p,
20751 wuffs_base__pixel_format dst_pixfmt,
20752 wuffs_base__slice_u8 dst_palette,
20753 wuffs_base__slice_u8 src_palette,
20754 wuffs_base__pixel_blend blend) {
20755 switch (dst_pixfmt.repr) {
20756 case WUFFS_BASE__PIXEL_FORMAT__Y:
20757 return wuffs_base__pixel_swizzler__copy_1_1;
20758
20759 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20760 return wuffs_base__pixel_swizzler__bgr_565__y;
20761
20762 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20763 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20764 return wuffs_base__pixel_swizzler__xxx__y;
20765
20766 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20767 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20768 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20769 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20770 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20771 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20772 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20773 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110020774#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100020775 if (wuffs_base__cpu_arch__have_x86_sse42()) {
20776 return wuffs_base__pixel_swizzler__xxxx__y__sse42;
20777 }
20778#endif
20779 return wuffs_base__pixel_swizzler__xxxx__y;
20780
20781 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20782 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
20783 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE:
20784 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE:
20785 return wuffs_base__pixel_swizzler__xxxxxxxx__y;
20786 }
20787 return NULL;
20788}
20789
20790static wuffs_base__pixel_swizzler__func //
20791wuffs_base__pixel_swizzler__prepare__y_16be(wuffs_base__pixel_swizzler* p,
20792 wuffs_base__pixel_format dst_pixfmt,
20793 wuffs_base__slice_u8 dst_palette,
20794 wuffs_base__slice_u8 src_palette,
20795 wuffs_base__pixel_blend blend) {
20796 switch (dst_pixfmt.repr) {
20797 case WUFFS_BASE__PIXEL_FORMAT__Y:
20798 return wuffs_base__pixel_swizzler__y__y_16be;
20799
Nigel Tao5571bfe2021-06-24 22:44:29 +100020800 case WUFFS_BASE__PIXEL_FORMAT__Y_16LE:
20801 return wuffs_base__pixel_swizzler__y_16le__y_16be;
20802
20803 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
20804 return wuffs_base__pixel_swizzler__copy_2_2;
20805
Nigel Taoe360a532021-04-05 22:47:03 +100020806 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20807 return wuffs_base__pixel_swizzler__bgr_565__y_16be;
20808
20809 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20810 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20811 return wuffs_base__pixel_swizzler__xxx__y_16be;
Nigel Taoe360a532021-04-05 22:47:03 +100020812
20813 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20814 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20815 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
20816 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
20817 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20818 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20819 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
20820 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20821 return wuffs_base__pixel_swizzler__xxxx__y_16be;
20822
20823 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20824 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
20825 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL_4X16LE:
20826 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL_4X16LE:
20827 return wuffs_base__pixel_swizzler__xxxxxxxx__y_16be;
20828 }
20829 return NULL;
20830}
20831
20832static wuffs_base__pixel_swizzler__func //
20833wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul(
20834 wuffs_base__pixel_swizzler* p,
20835 wuffs_base__pixel_format dst_pixfmt,
20836 wuffs_base__slice_u8 dst_palette,
20837 wuffs_base__slice_u8 src_palette,
20838 wuffs_base__pixel_blend blend) {
20839 switch (dst_pixfmt.repr) {
20840 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
20841 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20842 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20843 return NULL;
20844 }
20845 switch (blend) {
20846 case WUFFS_BASE__PIXEL_BLEND__SRC:
20847 return wuffs_base__pixel_swizzler__copy_1_1;
20848 }
20849 return NULL;
20850
20851 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
20852 switch (blend) {
20853 case WUFFS_BASE__PIXEL_BLEND__SRC:
20854 if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(
20855 dst_palette.ptr, dst_palette.len, src_palette.ptr,
20856 src_palette.len, true) !=
20857 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20858 return NULL;
20859 }
20860 return wuffs_base__pixel_swizzler__bgr_565__index__src;
20861 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20862 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20863 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20864 return NULL;
20865 }
20866 return wuffs_base__pixel_swizzler__bgr_565__index_bgra_nonpremul__src_over;
20867 }
20868 return NULL;
20869
20870 case WUFFS_BASE__PIXEL_FORMAT__BGR:
20871 switch (blend) {
20872 case WUFFS_BASE__PIXEL_BLEND__SRC:
20873 if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
20874 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20875 src_palette.len) !=
20876 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20877 return NULL;
20878 }
20879 return wuffs_base__pixel_swizzler__xxx__index__src;
20880 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20881 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20882 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20883 return NULL;
20884 }
20885 return wuffs_base__pixel_swizzler__xxx__index_bgra_nonpremul__src_over;
20886 }
20887 return NULL;
20888
20889 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
20890 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20891 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20892 return NULL;
20893 }
20894 switch (blend) {
20895 case WUFFS_BASE__PIXEL_BLEND__SRC:
20896 return wuffs_base__pixel_swizzler__xxxx__index__src;
20897 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20898 return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over;
20899 }
20900 return NULL;
20901
20902 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
20903 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20904 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20905 return NULL;
20906 }
20907 switch (blend) {
20908 case WUFFS_BASE__PIXEL_BLEND__SRC:
20909 return wuffs_base__pixel_swizzler__xxxxxxxx__index__src;
20910 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20911 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__index_bgra_nonpremul__src_over;
20912 }
20913 return NULL;
20914
20915 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
20916 switch (blend) {
20917 case WUFFS_BASE__PIXEL_BLEND__SRC:
20918 if (wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src(
20919 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20920 src_palette.len) !=
20921 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20922 return NULL;
20923 }
20924 return wuffs_base__pixel_swizzler__xxxx__index__src;
20925 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20926 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20927 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20928 return NULL;
20929 }
20930 return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over;
20931 }
20932 return NULL;
20933
20934 case WUFFS_BASE__PIXEL_FORMAT__RGB:
20935 // TODO.
20936 break;
20937
20938 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
20939 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20940 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20941 src_palette.len) !=
20942 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20943 return NULL;
20944 }
20945 switch (blend) {
20946 case WUFFS_BASE__PIXEL_BLEND__SRC:
20947 return wuffs_base__pixel_swizzler__xxxx__index__src;
20948 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20949 return wuffs_base__pixel_swizzler__bgra_nonpremul__index_bgra_nonpremul__src_over;
20950 }
20951 return NULL;
20952
20953 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
20954 switch (blend) {
20955 case WUFFS_BASE__PIXEL_BLEND__SRC:
20956 if (wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src(
20957 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20958 src_palette.len) !=
20959 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20960 return NULL;
20961 }
20962 return wuffs_base__pixel_swizzler__xxxx__index__src;
20963 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
20964 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
20965 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
20966 src_palette.len) !=
20967 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
20968 return NULL;
20969 }
20970 return wuffs_base__pixel_swizzler__bgra_premul__index_bgra_nonpremul__src_over;
20971 }
20972 return NULL;
20973
20974 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
20975 // TODO.
20976 break;
20977 }
20978 return NULL;
20979}
20980
20981static wuffs_base__pixel_swizzler__func //
20982wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary(
20983 wuffs_base__pixel_swizzler* p,
20984 wuffs_base__pixel_format dst_pixfmt,
20985 wuffs_base__slice_u8 dst_palette,
20986 wuffs_base__slice_u8 src_palette,
20987 wuffs_base__pixel_blend blend) {
20988 switch (dst_pixfmt.repr) {
20989 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
20990 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
20991 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
20992 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
20993 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
20994 return NULL;
20995 }
20996 switch (blend) {
20997 case WUFFS_BASE__PIXEL_BLEND__SRC:
20998 return wuffs_base__pixel_swizzler__copy_1_1;
20999 }
21000 return NULL;
21001
21002 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21003 if (wuffs_base__pixel_swizzler__squash_align4_bgr_565_8888(
21004 dst_palette.ptr, dst_palette.len, src_palette.ptr,
21005 src_palette.len, false) !=
21006 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
21007 return NULL;
21008 }
21009 switch (blend) {
21010 case WUFFS_BASE__PIXEL_BLEND__SRC:
21011 return wuffs_base__pixel_swizzler__bgr_565__index__src;
21012 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21013 return wuffs_base__pixel_swizzler__bgr_565__index_binary_alpha__src_over;
21014 }
21015 return NULL;
21016
21017 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21018 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
21019 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
21020 return NULL;
21021 }
21022 switch (blend) {
21023 case WUFFS_BASE__PIXEL_BLEND__SRC:
21024 return wuffs_base__pixel_swizzler__xxx__index__src;
21025 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21026 return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over;
21027 }
21028 return NULL;
21029
21030 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21031 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21032 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21033 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
21034 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
21035 return NULL;
21036 }
21037 switch (blend) {
21038 case WUFFS_BASE__PIXEL_BLEND__SRC:
21039 return wuffs_base__pixel_swizzler__xxxx__index__src;
21040 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21041 return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over;
21042 }
21043 return NULL;
21044
21045 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21046 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
21047 if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
21048 WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH) {
21049 return NULL;
21050 }
21051 switch (blend) {
21052 case WUFFS_BASE__PIXEL_BLEND__SRC:
21053 return wuffs_base__pixel_swizzler__xxxxxxxx__index__src;
21054 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21055 return wuffs_base__pixel_swizzler__xxxxxxxx__index_binary_alpha__src_over;
21056 }
21057 return NULL;
21058
21059 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21060 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
21061 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
21062 src_palette.len) !=
21063 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
21064 return NULL;
21065 }
21066 switch (blend) {
21067 case WUFFS_BASE__PIXEL_BLEND__SRC:
21068 return wuffs_base__pixel_swizzler__xxx__index__src;
21069 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21070 return wuffs_base__pixel_swizzler__xxx__index_binary_alpha__src_over;
21071 }
21072 return NULL;
21073
21074 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21075 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21076 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21077 if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(
21078 dst_palette.ptr, dst_palette.len, NULL, 0, src_palette.ptr,
21079 src_palette.len) !=
21080 (WUFFS_BASE__PIXEL_FORMAT__INDEXED__PALETTE_BYTE_LENGTH / 4)) {
21081 return NULL;
21082 }
21083 switch (blend) {
21084 case WUFFS_BASE__PIXEL_BLEND__SRC:
21085 return wuffs_base__pixel_swizzler__xxxx__index__src;
21086 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21087 return wuffs_base__pixel_swizzler__xxxx__index_binary_alpha__src_over;
21088 }
21089 return NULL;
21090 }
21091 return NULL;
21092}
21093
21094static wuffs_base__pixel_swizzler__func //
21095wuffs_base__pixel_swizzler__prepare__bgr_565(
21096 wuffs_base__pixel_swizzler* p,
21097 wuffs_base__pixel_format dst_pixfmt,
21098 wuffs_base__slice_u8 dst_palette,
21099 wuffs_base__slice_u8 src_palette,
21100 wuffs_base__pixel_blend blend) {
21101 switch (dst_pixfmt.repr) {
21102 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21103 return wuffs_base__pixel_swizzler__copy_2_2;
21104
21105 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21106 return wuffs_base__pixel_swizzler__bgr__bgr_565;
21107
21108 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21109 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21110 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21111 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21112 return wuffs_base__pixel_swizzler__bgrw__bgr_565;
21113
21114 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21115 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
21116 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr_565;
21117
21118 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21119 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21120 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21121 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21122 return wuffs_base__pixel_swizzler__rgbw__bgr_565;
21123 }
21124 return NULL;
21125}
21126
21127static wuffs_base__pixel_swizzler__func //
21128wuffs_base__pixel_swizzler__prepare__bgr(wuffs_base__pixel_swizzler* p,
21129 wuffs_base__pixel_format dst_pixfmt,
21130 wuffs_base__slice_u8 dst_palette,
21131 wuffs_base__slice_u8 src_palette,
21132 wuffs_base__pixel_blend blend) {
21133 switch (dst_pixfmt.repr) {
21134 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21135 return wuffs_base__pixel_swizzler__bgr_565__bgr;
21136
21137 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21138 return wuffs_base__pixel_swizzler__copy_3_3;
21139
21140 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21141 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21142 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21143 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21144 return wuffs_base__pixel_swizzler__bgrw__bgr;
21145
21146 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21147 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL_4X16LE:
21148 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgr;
21149
21150 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21151 return wuffs_base__pixel_swizzler__swap_rgb_bgr;
21152
21153 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21154 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21155 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21156 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021157#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021158 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21159 return wuffs_base__pixel_swizzler__bgrw__rgb__sse42;
21160 }
21161#endif
21162 return wuffs_base__pixel_swizzler__bgrw__rgb;
21163 }
21164 return NULL;
21165}
21166
21167static wuffs_base__pixel_swizzler__func //
21168wuffs_base__pixel_swizzler__prepare__bgra_nonpremul(
21169 wuffs_base__pixel_swizzler* p,
21170 wuffs_base__pixel_format dst_pixfmt,
21171 wuffs_base__slice_u8 dst_palette,
21172 wuffs_base__slice_u8 src_palette,
21173 wuffs_base__pixel_blend blend) {
21174 switch (dst_pixfmt.repr) {
21175 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21176 switch (blend) {
21177 case WUFFS_BASE__PIXEL_BLEND__SRC:
21178 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src;
21179 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21180 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul__src_over;
21181 }
21182 return NULL;
21183
21184 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21185 switch (blend) {
21186 case WUFFS_BASE__PIXEL_BLEND__SRC:
21187 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src;
21188 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21189 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul__src_over;
21190 }
21191 return NULL;
21192
21193 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21194 switch (blend) {
21195 case WUFFS_BASE__PIXEL_BLEND__SRC:
21196 return wuffs_base__pixel_swizzler__copy_4_4;
21197 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21198 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over;
21199 }
21200 return NULL;
21201
21202 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21203 switch (blend) {
21204 case WUFFS_BASE__PIXEL_BLEND__SRC:
21205 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src;
21206 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21207 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul__src_over;
21208 }
21209 return NULL;
21210
21211 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21212 switch (blend) {
21213 case WUFFS_BASE__PIXEL_BLEND__SRC:
21214 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src;
21215 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21216 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over;
21217 }
21218 return NULL;
21219
21220 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21221 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21222 // TODO.
21223 break;
21224
21225 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21226 // TODO.
21227 break;
21228
21229 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21230 switch (blend) {
21231 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021232#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021233 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21234 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
21235 }
21236#endif
21237 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
21238 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21239 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over;
21240 }
21241 return NULL;
21242
21243 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21244 switch (blend) {
21245 case WUFFS_BASE__PIXEL_BLEND__SRC:
21246 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src;
21247 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21248 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over;
21249 }
21250 return NULL;
21251
21252 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21253 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21254 // TODO.
21255 break;
21256 }
21257 return NULL;
21258}
21259
21260static wuffs_base__pixel_swizzler__func //
21261wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le(
21262 wuffs_base__pixel_swizzler* p,
21263 wuffs_base__pixel_format dst_pixfmt,
21264 wuffs_base__slice_u8 dst_palette,
21265 wuffs_base__slice_u8 src_palette,
21266 wuffs_base__pixel_blend blend) {
21267 switch (dst_pixfmt.repr) {
21268 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21269 switch (blend) {
21270 case WUFFS_BASE__PIXEL_BLEND__SRC:
21271 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src;
21272 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21273 return wuffs_base__pixel_swizzler__bgr_565__bgra_nonpremul_4x16le__src_over;
21274 }
21275 return NULL;
21276
21277 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21278 switch (blend) {
21279 case WUFFS_BASE__PIXEL_BLEND__SRC:
21280 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src;
21281 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21282 return wuffs_base__pixel_swizzler__bgr__bgra_nonpremul_4x16le__src_over;
21283 }
21284 return NULL;
21285
21286 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21287 switch (blend) {
21288 case WUFFS_BASE__PIXEL_BLEND__SRC:
21289 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src;
21290 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21291 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul_4x16le__src_over;
21292 }
21293 return NULL;
21294
21295 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21296 switch (blend) {
21297 case WUFFS_BASE__PIXEL_BLEND__SRC:
21298 return wuffs_base__pixel_swizzler__copy_8_8;
21299 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21300 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_nonpremul_4x16le__src_over;
21301 }
21302 return NULL;
21303
21304 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21305 switch (blend) {
21306 case WUFFS_BASE__PIXEL_BLEND__SRC:
21307 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src;
21308 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21309 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul_4x16le__src_over;
21310 }
21311 return NULL;
21312
21313 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21314 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21315 // TODO.
21316 break;
21317
21318 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21319 // TODO.
21320 break;
21321
21322 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21323 switch (blend) {
21324 case WUFFS_BASE__PIXEL_BLEND__SRC:
21325 return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src;
21326 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21327 return wuffs_base__pixel_swizzler__rgba_nonpremul__bgra_nonpremul_4x16le__src_over;
21328 }
21329 break;
21330
21331 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21332 switch (blend) {
21333 case WUFFS_BASE__PIXEL_BLEND__SRC:
21334 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src;
21335 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21336 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul_4x16le__src_over;
21337 }
21338 return NULL;
21339
21340 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21341 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21342 // TODO.
21343 break;
21344 }
21345 return NULL;
21346}
21347
21348static wuffs_base__pixel_swizzler__func //
21349wuffs_base__pixel_swizzler__prepare__bgra_premul(
21350 wuffs_base__pixel_swizzler* p,
21351 wuffs_base__pixel_format dst_pixfmt,
21352 wuffs_base__slice_u8 dst_palette,
21353 wuffs_base__slice_u8 src_palette,
21354 wuffs_base__pixel_blend blend) {
21355 switch (dst_pixfmt.repr) {
21356 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21357 switch (blend) {
21358 case WUFFS_BASE__PIXEL_BLEND__SRC:
21359 return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src;
21360 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21361 return wuffs_base__pixel_swizzler__bgr_565__bgra_premul__src_over;
21362 }
21363 return NULL;
21364
21365 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21366 switch (blend) {
21367 case WUFFS_BASE__PIXEL_BLEND__SRC:
21368 return wuffs_base__pixel_swizzler__bgr__bgra_premul__src;
21369 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21370 return wuffs_base__pixel_swizzler__bgr__bgra_premul__src_over;
21371 }
21372 return NULL;
21373
21374 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21375 switch (blend) {
21376 case WUFFS_BASE__PIXEL_BLEND__SRC:
21377 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src;
21378 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21379 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over;
21380 }
21381 return NULL;
21382
21383 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21384 switch (blend) {
21385 case WUFFS_BASE__PIXEL_BLEND__SRC:
21386 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src;
21387 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21388 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__bgra_premul__src_over;
21389 }
21390 return NULL;
21391
21392 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21393 switch (blend) {
21394 case WUFFS_BASE__PIXEL_BLEND__SRC:
21395 return wuffs_base__pixel_swizzler__copy_4_4;
21396 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21397 return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over;
21398 }
21399 return NULL;
21400
21401 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21402 switch (blend) {
21403 case WUFFS_BASE__PIXEL_BLEND__SRC:
21404 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src;
21405 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21406 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over;
21407 }
21408 return NULL;
21409
21410 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21411 switch (blend) {
21412 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021413#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021414 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21415 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
21416 }
21417#endif
21418 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
21419 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21420 return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over;
21421 }
21422 return NULL;
21423 }
21424 return NULL;
21425}
21426
21427static wuffs_base__pixel_swizzler__func //
21428wuffs_base__pixel_swizzler__prepare__bgrx(wuffs_base__pixel_swizzler* p,
21429 wuffs_base__pixel_format dst_pixfmt,
21430 wuffs_base__slice_u8 dst_palette,
21431 wuffs_base__slice_u8 src_palette,
21432 wuffs_base__pixel_blend blend) {
21433 switch (dst_pixfmt.repr) {
21434 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21435 return wuffs_base__pixel_swizzler__bgr_565__bgrx;
21436
21437 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21438 return wuffs_base__pixel_swizzler__xxx__xxxx;
21439
21440 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21441 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21442 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21443 return wuffs_base__pixel_swizzler__bgrw__bgrx;
21444
21445 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21446 return wuffs_base__pixel_swizzler__bgrw_4x16le__bgrx;
21447
21448 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21449 return wuffs_base__pixel_swizzler__copy_4_4;
21450
21451 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21452 // TODO.
21453 break;
21454
21455 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21456 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21457 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21458 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21459 return wuffs_base__pixel_swizzler__bgrw__rgbx;
21460 }
21461 return NULL;
21462}
21463
21464static wuffs_base__pixel_swizzler__func //
21465wuffs_base__pixel_swizzler__prepare__rgb(wuffs_base__pixel_swizzler* p,
21466 wuffs_base__pixel_format dst_pixfmt,
21467 wuffs_base__slice_u8 dst_palette,
21468 wuffs_base__slice_u8 src_palette,
21469 wuffs_base__pixel_blend blend) {
21470 switch (dst_pixfmt.repr) {
21471 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21472 return wuffs_base__pixel_swizzler__bgr_565__rgb;
21473
21474 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21475 return wuffs_base__pixel_swizzler__swap_rgb_bgr;
21476
21477 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21478 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21479 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21480 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021481#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021482 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21483 return wuffs_base__pixel_swizzler__bgrw__rgb__sse42;
21484 }
21485#endif
21486 return wuffs_base__pixel_swizzler__bgrw__rgb;
21487
21488 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21489 return wuffs_base__pixel_swizzler__bgrw_4x16le__rgb;
21490
21491 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21492 return wuffs_base__pixel_swizzler__copy_3_3;
21493
21494 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21495 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21496 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21497 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21498 return wuffs_base__pixel_swizzler__bgrw__bgr;
21499 }
21500 return NULL;
21501}
21502
21503static wuffs_base__pixel_swizzler__func //
21504wuffs_base__pixel_swizzler__prepare__rgba_nonpremul(
21505 wuffs_base__pixel_swizzler* p,
21506 wuffs_base__pixel_format dst_pixfmt,
21507 wuffs_base__slice_u8 dst_palette,
21508 wuffs_base__slice_u8 src_palette,
21509 wuffs_base__pixel_blend blend) {
21510 switch (dst_pixfmt.repr) {
21511 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21512 switch (blend) {
21513 case WUFFS_BASE__PIXEL_BLEND__SRC:
21514 return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src;
21515 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21516 return wuffs_base__pixel_swizzler__bgr_565__rgba_nonpremul__src_over;
21517 }
21518 return NULL;
21519
21520 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21521 switch (blend) {
21522 case WUFFS_BASE__PIXEL_BLEND__SRC:
21523 return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src;
21524 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21525 return wuffs_base__pixel_swizzler__bgr__rgba_nonpremul__src_over;
21526 }
21527 return NULL;
21528
21529 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21530 switch (blend) {
21531 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021532#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021533 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21534 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
21535 }
21536#endif
21537 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
21538 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21539 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_nonpremul__src_over;
21540 }
21541 return NULL;
21542
21543 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21544 switch (blend) {
21545 case WUFFS_BASE__PIXEL_BLEND__SRC:
21546 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src;
21547 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21548 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_nonpremul__src_over;
21549 }
21550 return NULL;
21551
21552 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21553 switch (blend) {
21554 case WUFFS_BASE__PIXEL_BLEND__SRC:
21555 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src;
21556 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21557 return wuffs_base__pixel_swizzler__bgra_premul__rgba_nonpremul__src_over;
21558 }
21559 return NULL;
21560
21561 case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
21562 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21563 // TODO.
21564 break;
21565
21566 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21567 // TODO.
21568 break;
21569
21570 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21571 switch (blend) {
21572 case WUFFS_BASE__PIXEL_BLEND__SRC:
21573 return wuffs_base__pixel_swizzler__copy_4_4;
21574 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21575 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_nonpremul__src_over;
21576 }
21577 return NULL;
21578
21579 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21580 switch (blend) {
21581 case WUFFS_BASE__PIXEL_BLEND__SRC:
21582 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src;
21583 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21584 return wuffs_base__pixel_swizzler__bgra_premul__bgra_nonpremul__src_over;
21585 }
21586 return NULL;
21587
21588 case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
21589 case WUFFS_BASE__PIXEL_FORMAT__RGBX:
21590 // TODO.
21591 break;
21592 }
21593 return NULL;
21594}
21595
21596static wuffs_base__pixel_swizzler__func //
21597wuffs_base__pixel_swizzler__prepare__rgba_premul(
21598 wuffs_base__pixel_swizzler* p,
21599 wuffs_base__pixel_format dst_pixfmt,
21600 wuffs_base__slice_u8 dst_palette,
21601 wuffs_base__slice_u8 src_palette,
21602 wuffs_base__pixel_blend blend) {
21603 switch (dst_pixfmt.repr) {
21604 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21605 switch (blend) {
21606 case WUFFS_BASE__PIXEL_BLEND__SRC:
21607 return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src;
21608 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21609 return wuffs_base__pixel_swizzler__bgr_565__rgba_premul__src_over;
21610 }
21611 return NULL;
21612
21613 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21614 switch (blend) {
21615 case WUFFS_BASE__PIXEL_BLEND__SRC:
21616 return wuffs_base__pixel_swizzler__bgr__rgba_premul__src;
21617 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21618 return wuffs_base__pixel_swizzler__bgr__rgba_premul__src_over;
21619 }
21620 return NULL;
21621
21622 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21623 switch (blend) {
21624 case WUFFS_BASE__PIXEL_BLEND__SRC:
21625 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src;
21626 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21627 return wuffs_base__pixel_swizzler__bgra_nonpremul__rgba_premul__src_over;
21628 }
21629 return NULL;
21630
21631 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21632 switch (blend) {
21633 case WUFFS_BASE__PIXEL_BLEND__SRC:
21634 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src;
21635 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21636 return wuffs_base__pixel_swizzler__bgra_nonpremul_4x16le__rgba_premul__src_over;
21637 }
21638 return NULL;
21639
21640 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21641 switch (blend) {
21642 case WUFFS_BASE__PIXEL_BLEND__SRC:
Nigel Tao7804ffe2021-10-07 21:58:26 +110021643#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100021644 if (wuffs_base__cpu_arch__have_x86_sse42()) {
21645 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx__sse42;
21646 }
21647#endif
21648 return wuffs_base__pixel_swizzler__swap_rgbx_bgrx;
21649 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21650 return wuffs_base__pixel_swizzler__bgra_premul__rgba_premul__src_over;
21651 }
21652 return NULL;
21653
21654 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21655 switch (blend) {
21656 case WUFFS_BASE__PIXEL_BLEND__SRC:
21657 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src;
21658 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21659 return wuffs_base__pixel_swizzler__bgra_nonpremul__bgra_premul__src_over;
21660 }
21661 return NULL;
21662
21663 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21664 switch (blend) {
21665 case WUFFS_BASE__PIXEL_BLEND__SRC:
21666 return wuffs_base__pixel_swizzler__copy_4_4;
21667 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21668 return wuffs_base__pixel_swizzler__bgra_premul__bgra_premul__src_over;
21669 }
21670 return NULL;
21671 }
21672 return NULL;
21673}
21674
21675// --------
21676
21677WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
21678wuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,
21679 wuffs_base__pixel_format dst_pixfmt,
21680 wuffs_base__slice_u8 dst_palette,
21681 wuffs_base__pixel_format src_pixfmt,
21682 wuffs_base__slice_u8 src_palette,
21683 wuffs_base__pixel_blend blend) {
21684 if (!p) {
21685 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
21686 }
21687 p->private_impl.func = NULL;
21688 p->private_impl.transparent_black_func = NULL;
21689 p->private_impl.dst_pixfmt_bytes_per_pixel = 0;
21690 p->private_impl.src_pixfmt_bytes_per_pixel = 0;
21691
21692 wuffs_base__pixel_swizzler__func func = NULL;
21693 wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func =
21694 NULL;
21695
21696 uint32_t dst_pixfmt_bits_per_pixel =
21697 wuffs_base__pixel_format__bits_per_pixel(&dst_pixfmt);
21698 if ((dst_pixfmt_bits_per_pixel == 0) ||
21699 ((dst_pixfmt_bits_per_pixel & 7) != 0)) {
21700 return wuffs_base__make_status(
21701 wuffs_base__error__unsupported_pixel_swizzler_option);
21702 }
21703
21704 uint32_t src_pixfmt_bits_per_pixel =
21705 wuffs_base__pixel_format__bits_per_pixel(&src_pixfmt);
21706 if ((src_pixfmt_bits_per_pixel == 0) ||
21707 ((src_pixfmt_bits_per_pixel & 7) != 0)) {
21708 return wuffs_base__make_status(
21709 wuffs_base__error__unsupported_pixel_swizzler_option);
21710 }
21711
21712 // TODO: support many more formats.
21713
21714 switch (blend) {
21715 case WUFFS_BASE__PIXEL_BLEND__SRC:
21716 transparent_black_func =
21717 wuffs_base__pixel_swizzler__transparent_black_src;
21718 break;
21719
21720 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
21721 transparent_black_func =
21722 wuffs_base__pixel_swizzler__transparent_black_src_over;
21723 break;
21724 }
21725
21726 switch (src_pixfmt.repr) {
21727 case WUFFS_BASE__PIXEL_FORMAT__Y:
21728 func = wuffs_base__pixel_swizzler__prepare__y(p, dst_pixfmt, dst_palette,
21729 src_palette, blend);
21730 break;
21731
21732 case WUFFS_BASE__PIXEL_FORMAT__Y_16BE:
21733 func = wuffs_base__pixel_swizzler__prepare__y_16be(
21734 p, dst_pixfmt, dst_palette, src_palette, blend);
21735 break;
21736
21737 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:
21738 func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_nonpremul(
21739 p, dst_pixfmt, dst_palette, src_palette, blend);
21740 break;
21741
21742 case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
21743 func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary(
21744 p, dst_pixfmt, dst_palette, src_palette, blend);
21745 break;
21746
21747 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
21748 func = wuffs_base__pixel_swizzler__prepare__bgr_565(
21749 p, dst_pixfmt, dst_palette, src_palette, blend);
21750 break;
21751
21752 case WUFFS_BASE__PIXEL_FORMAT__BGR:
21753 func = wuffs_base__pixel_swizzler__prepare__bgr(
21754 p, dst_pixfmt, dst_palette, src_palette, blend);
21755 break;
21756
21757 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
21758 func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul(
21759 p, dst_pixfmt, dst_palette, src_palette, blend);
21760 break;
21761
21762 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
21763 func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le(
21764 p, dst_pixfmt, dst_palette, src_palette, blend);
21765 break;
21766
21767 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
21768 func = wuffs_base__pixel_swizzler__prepare__bgra_premul(
21769 p, dst_pixfmt, dst_palette, src_palette, blend);
21770 break;
21771
21772 case WUFFS_BASE__PIXEL_FORMAT__BGRX:
21773 func = wuffs_base__pixel_swizzler__prepare__bgrx(
21774 p, dst_pixfmt, dst_palette, src_palette, blend);
21775 break;
21776
21777 case WUFFS_BASE__PIXEL_FORMAT__RGB:
21778 func = wuffs_base__pixel_swizzler__prepare__rgb(
21779 p, dst_pixfmt, dst_palette, src_palette, blend);
21780 break;
21781
21782 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
21783 func = wuffs_base__pixel_swizzler__prepare__rgba_nonpremul(
21784 p, dst_pixfmt, dst_palette, src_palette, blend);
21785 break;
21786
21787 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
21788 func = wuffs_base__pixel_swizzler__prepare__rgba_premul(
21789 p, dst_pixfmt, dst_palette, src_palette, blend);
21790 break;
21791 }
21792
21793 p->private_impl.func = func;
21794 p->private_impl.transparent_black_func = transparent_black_func;
21795 p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8;
21796 p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8;
21797 return wuffs_base__make_status(
21798 func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option);
21799}
21800
21801WUFFS_BASE__MAYBE_STATIC uint64_t //
21802wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
21803 const wuffs_base__pixel_swizzler* p,
21804 uint32_t up_to_num_pixels,
21805 wuffs_base__slice_u8 dst,
21806 wuffs_base__slice_u8 dst_palette,
21807 const uint8_t** ptr_iop_r,
21808 const uint8_t* io2_r) {
21809 if (p && p->private_impl.func) {
21810 const uint8_t* iop_r = *ptr_iop_r;
21811 uint64_t src_len = wuffs_base__u64__min(
21812 ((uint64_t)up_to_num_pixels) *
21813 ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel),
21814 ((uint64_t)(io2_r - iop_r)));
21815 uint64_t n =
21816 (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
21817 dst_palette.len, iop_r, (size_t)src_len);
21818 *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
21819 return n;
21820 }
21821 return 0;
21822}
21823
21824WUFFS_BASE__MAYBE_STATIC uint64_t //
21825wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
21826 const wuffs_base__pixel_swizzler* p,
21827 wuffs_base__slice_u8 dst,
21828 wuffs_base__slice_u8 dst_palette,
21829 const uint8_t** ptr_iop_r,
21830 const uint8_t* io2_r) {
21831 if (p && p->private_impl.func) {
21832 const uint8_t* iop_r = *ptr_iop_r;
21833 uint64_t src_len = ((uint64_t)(io2_r - iop_r));
21834 uint64_t n =
21835 (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
21836 dst_palette.len, iop_r, (size_t)src_len);
21837 *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
21838 return n;
21839 }
21840 return 0;
21841}
21842
21843WUFFS_BASE__MAYBE_STATIC uint64_t //
21844wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(
21845 const wuffs_base__pixel_swizzler* p,
21846 wuffs_base__slice_u8 dst,
21847 wuffs_base__slice_u8 dst_palette,
21848 wuffs_base__slice_u8 src) {
21849 if (p && p->private_impl.func) {
21850 return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
21851 dst_palette.len, src.ptr, src.len);
21852 }
21853 return 0;
21854}
21855
21856WUFFS_BASE__MAYBE_STATIC uint64_t //
21857wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(
21858 const wuffs_base__pixel_swizzler* p,
21859 wuffs_base__slice_u8 dst,
21860 wuffs_base__slice_u8 dst_palette,
21861 uint64_t num_pixels) {
21862 if (p && p->private_impl.transparent_black_func) {
21863 return (*p->private_impl.transparent_black_func)(
21864 dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels,
21865 p->private_impl.dst_pixfmt_bytes_per_pixel);
21866 }
21867 return 0;
21868}
21869
21870#endif // !defined(WUFFS_CONFIG__MODULES) ||
21871 // defined(WUFFS_CONFIG__MODULE__BASE) ||
21872 // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)
21873
21874#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \
21875 defined(WUFFS_CONFIG__MODULE__BASE__UTF8)
21876
21877// ---------------- Unicode and UTF-8
21878
21879WUFFS_BASE__MAYBE_STATIC size_t //
21880wuffs_base__utf_8__encode(wuffs_base__slice_u8 dst, uint32_t code_point) {
21881 if (code_point <= 0x7F) {
21882 if (dst.len >= 1) {
21883 dst.ptr[0] = (uint8_t)(code_point);
21884 return 1;
21885 }
21886
21887 } else if (code_point <= 0x07FF) {
21888 if (dst.len >= 2) {
21889 dst.ptr[0] = (uint8_t)(0xC0 | ((code_point >> 6)));
21890 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
21891 return 2;
21892 }
21893
21894 } else if (code_point <= 0xFFFF) {
21895 if ((dst.len >= 3) && ((code_point < 0xD800) || (0xDFFF < code_point))) {
21896 dst.ptr[0] = (uint8_t)(0xE0 | ((code_point >> 12)));
21897 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F));
21898 dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
21899 return 3;
21900 }
21901
21902 } else if (code_point <= 0x10FFFF) {
21903 if (dst.len >= 4) {
21904 dst.ptr[0] = (uint8_t)(0xF0 | ((code_point >> 18)));
21905 dst.ptr[1] = (uint8_t)(0x80 | ((code_point >> 12) & 0x3F));
21906 dst.ptr[2] = (uint8_t)(0x80 | ((code_point >> 6) & 0x3F));
21907 dst.ptr[3] = (uint8_t)(0x80 | ((code_point >> 0) & 0x3F));
21908 return 4;
21909 }
21910 }
21911
21912 return 0;
21913}
21914
21915// wuffs_base__utf_8__byte_length_minus_1 is the byte length (minus 1) of a
21916// UTF-8 encoded code point, based on the encoding's initial byte.
21917// - 0x00 is 1-byte UTF-8 (ASCII).
21918// - 0x01 is the start of 2-byte UTF-8.
21919// - 0x02 is the start of 3-byte UTF-8.
21920// - 0x03 is the start of 4-byte UTF-8.
21921// - 0x40 is a UTF-8 tail byte.
21922// - 0x80 is invalid UTF-8.
21923//
21924// RFC 3629 (UTF-8) gives this grammar for valid UTF-8:
21925// UTF8-1 = %x00-7F
21926// UTF8-2 = %xC2-DF UTF8-tail
21927// UTF8-3 = %xE0 %xA0-BF UTF8-tail / %xE1-EC 2( UTF8-tail ) /
21928// %xED %x80-9F UTF8-tail / %xEE-EF 2( UTF8-tail )
21929// UTF8-4 = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
21930// %xF4 %x80-8F 2( UTF8-tail )
21931// UTF8-tail = %x80-BF
21932static const uint8_t wuffs_base__utf_8__byte_length_minus_1[256] = {
21933 // 0 1 2 3 4 5 6 7
21934 // 8 9 A B C D E F
21935 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00 ..= 0x07.
21936 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x08 ..= 0x0F.
21937 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x10 ..= 0x17.
21938 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x18 ..= 0x1F.
21939 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x20 ..= 0x27.
21940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x28 ..= 0x2F.
21941 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x30 ..= 0x37.
21942 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x38 ..= 0x3F.
21943
21944 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x40 ..= 0x47.
21945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x48 ..= 0x4F.
21946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x50 ..= 0x57.
21947 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x58 ..= 0x5F.
21948 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x60 ..= 0x67.
21949 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x68 ..= 0x6F.
21950 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x70 ..= 0x77.
21951 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x78 ..= 0x7F.
21952
21953 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x80 ..= 0x87.
21954 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x88 ..= 0x8F.
21955 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x90 ..= 0x97.
21956 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0x98 ..= 0x9F.
21957 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA0 ..= 0xA7.
21958 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xA8 ..= 0xAF.
21959 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB0 ..= 0xB7.
21960 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // 0xB8 ..= 0xBF.
21961
21962 0x80, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC0 ..= 0xC7.
21963 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xC8 ..= 0xCF.
21964 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD0 ..= 0xD7.
21965 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, // 0xD8 ..= 0xDF.
21966 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE0 ..= 0xE7.
21967 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xE8 ..= 0xEF.
21968 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0x80, 0x80, // 0xF0 ..= 0xF7.
21969 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // 0xF8 ..= 0xFF.
21970 // 0 1 2 3 4 5 6 7
21971 // 8 9 A B C D E F
21972};
21973
21974WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
21975wuffs_base__utf_8__next(const uint8_t* s_ptr, size_t s_len) {
21976 if (s_len == 0) {
21977 return wuffs_base__make_utf_8__next__output(0, 0);
21978 }
21979 uint32_t c = s_ptr[0];
21980 switch (wuffs_base__utf_8__byte_length_minus_1[c & 0xFF]) {
21981 case 0:
21982 return wuffs_base__make_utf_8__next__output(c, 1);
21983
21984 case 1:
21985 if (s_len < 2) {
21986 break;
21987 }
21988 c = wuffs_base__peek_u16le__no_bounds_check(s_ptr);
21989 if ((c & 0xC000) != 0x8000) {
21990 break;
21991 }
21992 c = (0x0007C0 & (c << 6)) | (0x00003F & (c >> 8));
21993 return wuffs_base__make_utf_8__next__output(c, 2);
21994
21995 case 2:
21996 if (s_len < 3) {
21997 break;
21998 }
21999 c = wuffs_base__peek_u24le__no_bounds_check(s_ptr);
22000 if ((c & 0xC0C000) != 0x808000) {
22001 break;
22002 }
22003 c = (0x00F000 & (c << 12)) | (0x000FC0 & (c >> 2)) |
22004 (0x00003F & (c >> 16));
22005 if ((c <= 0x07FF) || ((0xD800 <= c) && (c <= 0xDFFF))) {
22006 break;
22007 }
22008 return wuffs_base__make_utf_8__next__output(c, 3);
22009
22010 case 3:
22011 if (s_len < 4) {
22012 break;
22013 }
22014 c = wuffs_base__peek_u32le__no_bounds_check(s_ptr);
22015 if ((c & 0xC0C0C000) != 0x80808000) {
22016 break;
22017 }
22018 c = (0x1C0000 & (c << 18)) | (0x03F000 & (c << 4)) |
22019 (0x000FC0 & (c >> 10)) | (0x00003F & (c >> 24));
22020 if ((c <= 0xFFFF) || (0x110000 <= c)) {
22021 break;
22022 }
22023 return wuffs_base__make_utf_8__next__output(c, 4);
22024 }
22025
22026 return wuffs_base__make_utf_8__next__output(
22027 WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1);
22028}
22029
22030WUFFS_BASE__MAYBE_STATIC wuffs_base__utf_8__next__output //
22031wuffs_base__utf_8__next_from_end(const uint8_t* s_ptr, size_t s_len) {
22032 if (s_len == 0) {
22033 return wuffs_base__make_utf_8__next__output(0, 0);
22034 }
22035 const uint8_t* ptr = &s_ptr[s_len - 1];
22036 if (*ptr < 0x80) {
22037 return wuffs_base__make_utf_8__next__output(*ptr, 1);
22038
22039 } else if (*ptr < 0xC0) {
22040 const uint8_t* too_far = &s_ptr[(s_len > 4) ? (s_len - 4) : 0];
22041 uint32_t n = 1;
22042 while (ptr != too_far) {
22043 ptr--;
22044 n++;
22045 if (*ptr < 0x80) {
22046 break;
22047 } else if (*ptr < 0xC0) {
22048 continue;
22049 }
22050 wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(ptr, n);
22051 if (o.byte_length != n) {
22052 break;
22053 }
22054 return o;
22055 }
22056 }
22057
22058 return wuffs_base__make_utf_8__next__output(
22059 WUFFS_BASE__UNICODE_REPLACEMENT_CHARACTER, 1);
22060}
22061
22062WUFFS_BASE__MAYBE_STATIC size_t //
22063wuffs_base__utf_8__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
22064 // TODO: possibly optimize the all-ASCII case (4 or 8 bytes at a time).
22065 //
22066 // TODO: possibly optimize this by manually inlining the
22067 // wuffs_base__utf_8__next calls.
22068 size_t original_len = s_len;
22069 while (s_len > 0) {
22070 wuffs_base__utf_8__next__output o = wuffs_base__utf_8__next(s_ptr, s_len);
22071 if ((o.code_point > 0x7F) && (o.byte_length == 1)) {
22072 break;
22073 }
22074 s_ptr += o.byte_length;
22075 s_len -= o.byte_length;
22076 }
22077 return original_len - s_len;
22078}
22079
22080WUFFS_BASE__MAYBE_STATIC size_t //
22081wuffs_base__ascii__longest_valid_prefix(const uint8_t* s_ptr, size_t s_len) {
22082 // TODO: possibly optimize this by checking 4 or 8 bytes at a time.
22083 const uint8_t* original_ptr = s_ptr;
22084 const uint8_t* p = s_ptr;
22085 const uint8_t* q = s_ptr + s_len;
22086 for (; (p != q) && ((*p & 0x80) == 0); p++) {
22087 }
22088 return (size_t)(p - original_ptr);
22089}
22090
22091#endif // !defined(WUFFS_CONFIG__MODULES) ||
22092 // defined(WUFFS_CONFIG__MODULE__BASE) ||
22093 // defined(WUFFS_CONFIG__MODULE__BASE__UTF8)
22094
22095#ifdef __cplusplus
22096} // extern "C"
22097#endif
22098
22099#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32)
22100
22101// ---------------- Status Codes Implementations
22102
22103// ---------------- Private Consts
22104
22105// ---------------- Private Initializer Prototypes
22106
22107// ---------------- Private Function Prototypes
22108
22109static wuffs_base__empty_struct
22110wuffs_adler32__hasher__up(
22111 wuffs_adler32__hasher* self,
22112 wuffs_base__slice_u8 a_x);
22113
22114static wuffs_base__empty_struct
22115wuffs_adler32__hasher__up__choosy_default(
22116 wuffs_adler32__hasher* self,
22117 wuffs_base__slice_u8 a_x);
22118
22119#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
22120static wuffs_base__empty_struct
22121wuffs_adler32__hasher__up_arm_neon(
22122 wuffs_adler32__hasher* self,
22123 wuffs_base__slice_u8 a_x);
22124#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
22125
Nigel Tao7804ffe2021-10-07 21:58:26 +110022126#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100022127static wuffs_base__empty_struct
22128wuffs_adler32__hasher__up_x86_sse42(
22129 wuffs_adler32__hasher* self,
22130 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110022131#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100022132
22133// ---------------- VTables
22134
22135const wuffs_base__hasher_u32__func_ptrs
22136wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32 = {
22137 (wuffs_base__empty_struct(*)(void*,
22138 uint32_t,
22139 bool))(&wuffs_adler32__hasher__set_quirk_enabled),
22140 (uint32_t(*)(void*,
22141 wuffs_base__slice_u8))(&wuffs_adler32__hasher__update_u32),
22142};
22143
22144// ---------------- Initializer Implementations
22145
22146wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
22147wuffs_adler32__hasher__initialize(
22148 wuffs_adler32__hasher* self,
22149 size_t sizeof_star_self,
22150 uint64_t wuffs_version,
22151 uint32_t options){
22152 if (!self) {
22153 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
22154 }
22155 if (sizeof(*self) != sizeof_star_self) {
22156 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
22157 }
22158 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
22159 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
22160 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
22161 }
22162
22163 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
22164 // The whole point of this if-check is to detect an uninitialized *self.
22165 // We disable the warning on GCC. Clang-5.0 does not have this warning.
22166#if !defined(__clang__) && defined(__GNUC__)
22167#pragma GCC diagnostic push
22168#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
22169#endif
22170 if (self->private_impl.magic != 0) {
22171 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
22172 }
22173#if !defined(__clang__) && defined(__GNUC__)
22174#pragma GCC diagnostic pop
22175#endif
22176 } else {
22177 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
22178 memset(self, 0, sizeof(*self));
22179 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
22180 } else {
22181 memset(&(self->private_impl), 0, sizeof(self->private_impl));
22182 }
22183 }
22184
22185 self->private_impl.choosy_up = &wuffs_adler32__hasher__up__choosy_default;
22186
22187 self->private_impl.magic = WUFFS_BASE__MAGIC;
22188 self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name =
22189 wuffs_base__hasher_u32__vtable_name;
22190 self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers =
22191 (const void*)(&wuffs_adler32__hasher__func_ptrs_for__wuffs_base__hasher_u32);
22192 return wuffs_base__make_status(NULL);
22193}
22194
22195wuffs_adler32__hasher*
22196wuffs_adler32__hasher__alloc() {
22197 wuffs_adler32__hasher* x =
22198 (wuffs_adler32__hasher*)(calloc(sizeof(wuffs_adler32__hasher), 1));
22199 if (!x) {
22200 return NULL;
22201 }
22202 if (wuffs_adler32__hasher__initialize(
22203 x, sizeof(wuffs_adler32__hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
22204 free(x);
22205 return NULL;
22206 }
22207 return x;
22208}
22209
22210size_t
22211sizeof__wuffs_adler32__hasher() {
22212 return sizeof(wuffs_adler32__hasher);
22213}
22214
22215// ---------------- Function Implementations
22216
22217// -------- func adler32.hasher.set_quirk_enabled
22218
22219WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
22220wuffs_adler32__hasher__set_quirk_enabled(
22221 wuffs_adler32__hasher* self,
22222 uint32_t a_quirk,
22223 bool a_enabled) {
22224 return wuffs_base__make_empty_struct();
22225}
22226
22227// -------- func adler32.hasher.update_u32
22228
22229WUFFS_BASE__MAYBE_STATIC uint32_t
22230wuffs_adler32__hasher__update_u32(
22231 wuffs_adler32__hasher* self,
22232 wuffs_base__slice_u8 a_x) {
22233 if (!self) {
22234 return 0;
22235 }
22236 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
22237 return 0;
22238 }
22239
22240 if ( ! self->private_impl.f_started) {
22241 self->private_impl.f_started = true;
22242 self->private_impl.f_state = 1;
22243 self->private_impl.choosy_up = (
22244#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
22245 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_adler32__hasher__up_arm_neon :
22246#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110022247#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100022248 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_adler32__hasher__up_x86_sse42 :
22249#endif
22250 self->private_impl.choosy_up);
22251 }
22252 wuffs_adler32__hasher__up(self, a_x);
22253 return self->private_impl.f_state;
22254}
22255
22256// -------- func adler32.hasher.up
22257
22258static wuffs_base__empty_struct
22259wuffs_adler32__hasher__up(
22260 wuffs_adler32__hasher* self,
22261 wuffs_base__slice_u8 a_x) {
22262 return (*self->private_impl.choosy_up)(self, a_x);
22263}
22264
22265static wuffs_base__empty_struct
22266wuffs_adler32__hasher__up__choosy_default(
22267 wuffs_adler32__hasher* self,
22268 wuffs_base__slice_u8 a_x) {
22269 uint32_t v_s1 = 0;
22270 uint32_t v_s2 = 0;
22271 wuffs_base__slice_u8 v_remaining = {0};
22272 wuffs_base__slice_u8 v_p = {0};
22273
22274 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
22275 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
22276 while (((uint64_t)(a_x.len)) > 0) {
22277 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
22278 if (((uint64_t)(a_x.len)) > 5552) {
22279 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5552);
22280 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5552);
22281 }
22282 {
22283 wuffs_base__slice_u8 i_slice_p = a_x;
22284 v_p.ptr = i_slice_p.ptr;
22285 v_p.len = 1;
22286 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8);
22287 while (v_p.ptr < i_end0_p) {
22288 v_s1 += ((uint32_t)(v_p.ptr[0]));
22289 v_s2 += v_s1;
22290 v_p.ptr += 1;
22291 v_s1 += ((uint32_t)(v_p.ptr[0]));
22292 v_s2 += v_s1;
22293 v_p.ptr += 1;
22294 v_s1 += ((uint32_t)(v_p.ptr[0]));
22295 v_s2 += v_s1;
22296 v_p.ptr += 1;
22297 v_s1 += ((uint32_t)(v_p.ptr[0]));
22298 v_s2 += v_s1;
22299 v_p.ptr += 1;
22300 v_s1 += ((uint32_t)(v_p.ptr[0]));
22301 v_s2 += v_s1;
22302 v_p.ptr += 1;
22303 v_s1 += ((uint32_t)(v_p.ptr[0]));
22304 v_s2 += v_s1;
22305 v_p.ptr += 1;
22306 v_s1 += ((uint32_t)(v_p.ptr[0]));
22307 v_s2 += v_s1;
22308 v_p.ptr += 1;
22309 v_s1 += ((uint32_t)(v_p.ptr[0]));
22310 v_s2 += v_s1;
22311 v_p.ptr += 1;
22312 }
22313 v_p.len = 1;
22314 uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len;
22315 while (v_p.ptr < i_end1_p) {
22316 v_s1 += ((uint32_t)(v_p.ptr[0]));
22317 v_s2 += v_s1;
22318 v_p.ptr += 1;
22319 }
22320 v_p.len = 0;
22321 }
22322 v_s1 %= 65521;
22323 v_s2 %= 65521;
22324 a_x = v_remaining;
22325 }
22326 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
22327 return wuffs_base__make_empty_struct();
22328}
22329
22330// ‼ WUFFS MULTI-FILE SECTION +arm_neon
22331// -------- func adler32.hasher.up_arm_neon
22332
22333#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
22334static wuffs_base__empty_struct
22335wuffs_adler32__hasher__up_arm_neon(
22336 wuffs_adler32__hasher* self,
22337 wuffs_base__slice_u8 a_x) {
22338 uint32_t v_s1 = 0;
22339 uint32_t v_s2 = 0;
22340 wuffs_base__slice_u8 v_remaining = {0};
22341 wuffs_base__slice_u8 v_p = {0};
22342 uint8x16_t v_p__left = {0};
22343 uint8x16_t v_p_right = {0};
22344 uint32x4_t v_v1 = {0};
22345 uint32x4_t v_v2 = {0};
22346 uint16x8_t v_col0 = {0};
22347 uint16x8_t v_col1 = {0};
22348 uint16x8_t v_col2 = {0};
22349 uint16x8_t v_col3 = {0};
22350 uint32x2_t v_sum1 = {0};
22351 uint32x2_t v_sum2 = {0};
22352 uint32x2_t v_sum12 = {0};
22353 uint32_t v_num_iterate_bytes = 0;
22354 uint64_t v_tail_index = 0;
22355
22356 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
22357 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
22358 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
22359 v_s1 += ((uint32_t)(a_x.ptr[0]));
22360 v_s2 += v_s1;
22361 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
22362 }
22363 v_s1 %= 65521;
22364 v_s2 %= 65521;
22365 while (((uint64_t)(a_x.len)) > 0) {
22366 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
22367 if (((uint64_t)(a_x.len)) > 5536) {
22368 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536);
22369 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536);
22370 }
22371 v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264)));
22372 v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes));
22373 v_v1 = vdupq_n_u32(0);
22374 v_v2 = vdupq_n_u32(0);
22375 v_col0 = vdupq_n_u16(0);
22376 v_col1 = vdupq_n_u16(0);
22377 v_col2 = vdupq_n_u16(0);
22378 v_col3 = vdupq_n_u16(0);
22379 {
22380 wuffs_base__slice_u8 i_slice_p = a_x;
22381 v_p.ptr = i_slice_p.ptr;
22382 v_p.len = 32;
22383 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
22384 while (v_p.ptr < i_end0_p) {
22385 v_p__left = vld1q_u8(v_p.ptr);
22386 v_p_right = vld1q_u8(v_p.ptr + 16);
22387 v_v2 = vaddq_u32(v_v2, v_v1);
22388 v_v1 = vpadalq_u16(v_v1, vpadalq_u8(vpaddlq_u8(v_p__left), v_p_right));
22389 v_col0 = vaddw_u8(v_col0, vget_low_u8(v_p__left));
22390 v_col1 = vaddw_u8(v_col1, vget_high_u8(v_p__left));
22391 v_col2 = vaddw_u8(v_col2, vget_low_u8(v_p_right));
22392 v_col3 = vaddw_u8(v_col3, vget_high_u8(v_p_right));
22393 v_p.ptr += 32;
22394 }
22395 v_p.len = 0;
22396 }
22397 v_v2 = vshlq_n_u32(v_v2, 5);
22398 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col0), ((uint16x4_t){32, 31, 30, 29}));
22399 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col0), ((uint16x4_t){28, 27, 26, 25}));
22400 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col1), ((uint16x4_t){24, 23, 22, 21}));
22401 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col1), ((uint16x4_t){20, 19, 18, 17}));
22402 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col2), ((uint16x4_t){16, 15, 14, 13}));
22403 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col2), ((uint16x4_t){12, 11, 10, 9}));
22404 v_v2 = vmlal_u16(v_v2, vget_low_u16(v_col3), ((uint16x4_t){8, 7, 6, 5}));
22405 v_v2 = vmlal_u16(v_v2, vget_high_u16(v_col3), ((uint16x4_t){4, 3, 2, 1}));
22406 v_sum1 = vpadd_u32(vget_low_u32(v_v1), vget_high_u32(v_v1));
22407 v_sum2 = vpadd_u32(vget_low_u32(v_v2), vget_high_u32(v_v2));
22408 v_sum12 = vpadd_u32(v_sum1, v_sum2);
22409 v_s1 += vget_lane_u32(v_sum12, 0);
22410 v_s2 += vget_lane_u32(v_sum12, 1);
22411 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u);
22412 if (v_tail_index < ((uint64_t)(a_x.len))) {
22413 {
22414 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
22415 v_p.ptr = i_slice_p.ptr;
22416 v_p.len = 1;
22417 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
22418 while (v_p.ptr < i_end0_p) {
22419 v_s1 += ((uint32_t)(v_p.ptr[0]));
22420 v_s2 += v_s1;
22421 v_p.ptr += 1;
22422 }
22423 v_p.len = 0;
22424 }
22425 }
22426 v_s1 %= 65521;
22427 v_s2 %= 65521;
22428 a_x = v_remaining;
22429 }
22430 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
22431 return wuffs_base__make_empty_struct();
22432}
22433#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
22434// ‼ WUFFS MULTI-FILE SECTION -arm_neon
22435
22436// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
22437// -------- func adler32.hasher.up_x86_sse42
22438
Nigel Tao7804ffe2021-10-07 21:58:26 +110022439#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100022440WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
22441static wuffs_base__empty_struct
22442wuffs_adler32__hasher__up_x86_sse42(
22443 wuffs_adler32__hasher* self,
22444 wuffs_base__slice_u8 a_x) {
22445 uint32_t v_s1 = 0;
22446 uint32_t v_s2 = 0;
22447 wuffs_base__slice_u8 v_remaining = {0};
22448 wuffs_base__slice_u8 v_p = {0};
22449 __m128i v_zeroes = {0};
22450 __m128i v_ones = {0};
22451 __m128i v_weights__left = {0};
22452 __m128i v_weights_right = {0};
Nigel Tao5571bfe2021-06-24 22:44:29 +100022453 __m128i v_q__left = {0};
22454 __m128i v_q_right = {0};
Nigel Taoe360a532021-04-05 22:47:03 +100022455 __m128i v_v1 = {0};
22456 __m128i v_v2 = {0};
22457 __m128i v_v2j = {0};
22458 __m128i v_v2k = {0};
22459 uint32_t v_num_iterate_bytes = 0;
22460 uint64_t v_tail_index = 0;
22461
22462 v_zeroes = _mm_set1_epi16((int16_t)(0));
22463 v_ones = _mm_set1_epi16((int16_t)(1));
22464 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));
22465 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));
22466 v_s1 = ((self->private_impl.f_state) & 0xFFFF);
22467 v_s2 = ((self->private_impl.f_state) >> (32 - (16)));
22468 while (((uint64_t)(a_x.len)) > 0) {
22469 v_remaining = wuffs_base__slice_u8__subslice_j(a_x, 0);
22470 if (((uint64_t)(a_x.len)) > 5536) {
22471 v_remaining = wuffs_base__slice_u8__subslice_i(a_x, 5536);
22472 a_x = wuffs_base__slice_u8__subslice_j(a_x, 5536);
22473 }
22474 v_num_iterate_bytes = ((uint32_t)((((uint64_t)(a_x.len)) & 4294967264)));
22475 v_s2 += ((uint32_t)(v_s1 * v_num_iterate_bytes));
22476 v_v1 = _mm_setzero_si128();
22477 v_v2j = _mm_setzero_si128();
22478 v_v2k = _mm_setzero_si128();
22479 {
22480 wuffs_base__slice_u8 i_slice_p = a_x;
22481 v_p.ptr = i_slice_p.ptr;
22482 v_p.len = 32;
22483 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
22484 while (v_p.ptr < i_end0_p) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100022485 v_q__left = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr));
22486 v_q_right = _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16));
Nigel Taoe360a532021-04-05 22:47:03 +100022487 v_v2j = _mm_add_epi32(v_v2j, v_v1);
Nigel Tao5571bfe2021-06-24 22:44:29 +100022488 v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q__left, v_zeroes));
22489 v_v1 = _mm_add_epi32(v_v1, _mm_sad_epu8(v_q_right, v_zeroes));
22490 v_v2k = _mm_add_epi32(v_v2k, _mm_madd_epi16(v_ones, _mm_maddubs_epi16(v_q__left, v_weights__left)));
22491 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 +100022492 v_p.ptr += 32;
22493 }
22494 v_p.len = 0;
22495 }
22496 v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(177)));
22497 v_v1 = _mm_add_epi32(v_v1, _mm_shuffle_epi32(v_v1, (int32_t)(78)));
22498 v_s1 += ((uint32_t)(_mm_cvtsi128_si32(v_v1)));
22499 v_v2 = _mm_add_epi32(v_v2k, _mm_slli_epi32(v_v2j, (int32_t)(5)));
22500 v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(177)));
22501 v_v2 = _mm_add_epi32(v_v2, _mm_shuffle_epi32(v_v2, (int32_t)(78)));
22502 v_s2 += ((uint32_t)(_mm_cvtsi128_si32(v_v2)));
22503 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551584u);
22504 if (v_tail_index < ((uint64_t)(a_x.len))) {
22505 {
22506 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
22507 v_p.ptr = i_slice_p.ptr;
22508 v_p.len = 1;
22509 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
22510 while (v_p.ptr < i_end0_p) {
22511 v_s1 += ((uint32_t)(v_p.ptr[0]));
22512 v_s2 += v_s1;
22513 v_p.ptr += 1;
22514 }
22515 v_p.len = 0;
22516 }
22517 }
22518 v_s1 %= 65521;
22519 v_s2 %= 65521;
22520 a_x = v_remaining;
22521 }
22522 self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535));
22523 return wuffs_base__make_empty_struct();
22524}
Nigel Tao7804ffe2021-10-07 21:58:26 +110022525#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100022526// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
22527
22528#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ADLER32)
22529
22530#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
22531
22532// ---------------- Status Codes Implementations
22533
22534const char wuffs_bmp__error__bad_header[] = "#bmp: bad header";
22535const char wuffs_bmp__error__bad_rle_compression[] = "#bmp: bad RLE compression";
22536const char wuffs_bmp__error__unsupported_bmp_file[] = "#bmp: unsupported BMP file";
22537const char wuffs_bmp__note__internal_note_short_read[] = "@bmp: internal note: short read";
22538
22539// ---------------- Private Consts
22540
22541#define WUFFS_BMP__COMPRESSION_NONE 0
22542
22543#define WUFFS_BMP__COMPRESSION_RLE8 1
22544
22545#define WUFFS_BMP__COMPRESSION_RLE4 2
22546
22547#define WUFFS_BMP__COMPRESSION_BITFIELDS 3
22548
22549#define WUFFS_BMP__COMPRESSION_JPEG 4
22550
22551#define WUFFS_BMP__COMPRESSION_PNG 5
22552
22553#define WUFFS_BMP__COMPRESSION_ALPHABITFIELDS 6
22554
22555#define WUFFS_BMP__COMPRESSION_LOW_BIT_DEPTH 256
22556
22557#define WUFFS_BMP__RLE_STATE_NEUTRAL 0
22558
22559#define WUFFS_BMP__RLE_STATE_RUN 1
22560
22561#define WUFFS_BMP__RLE_STATE_ESCAPE 2
22562
22563#define WUFFS_BMP__RLE_STATE_LITERAL 3
22564
22565#define WUFFS_BMP__RLE_STATE_DELTA_X 4
22566
22567#define WUFFS_BMP__RLE_STATE_DELTA_Y 5
22568
22569// ---------------- Private Initializer Prototypes
22570
22571// ---------------- Private Function Prototypes
22572
22573static wuffs_base__status
22574wuffs_bmp__decoder__swizzle_none(
22575 wuffs_bmp__decoder* self,
22576 wuffs_base__pixel_buffer* a_dst,
22577 wuffs_base__io_buffer* a_src);
22578
22579static wuffs_base__status
22580wuffs_bmp__decoder__swizzle_rle(
22581 wuffs_bmp__decoder* self,
22582 wuffs_base__pixel_buffer* a_dst,
22583 wuffs_base__io_buffer* a_src);
22584
22585static wuffs_base__status
22586wuffs_bmp__decoder__swizzle_bitfields(
22587 wuffs_bmp__decoder* self,
22588 wuffs_base__pixel_buffer* a_dst,
22589 wuffs_base__io_buffer* a_src);
22590
22591static wuffs_base__status
22592wuffs_bmp__decoder__swizzle_low_bit_depth(
22593 wuffs_bmp__decoder* self,
22594 wuffs_base__pixel_buffer* a_dst,
22595 wuffs_base__io_buffer* a_src);
22596
22597static wuffs_base__status
22598wuffs_bmp__decoder__read_palette(
22599 wuffs_bmp__decoder* self,
22600 wuffs_base__io_buffer* a_src);
22601
22602static wuffs_base__status
22603wuffs_bmp__decoder__process_masks(
22604 wuffs_bmp__decoder* self);
22605
22606// ---------------- VTables
22607
22608const wuffs_base__image_decoder__func_ptrs
22609wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder = {
22610 (wuffs_base__status(*)(void*,
22611 wuffs_base__pixel_buffer*,
22612 wuffs_base__io_buffer*,
22613 wuffs_base__pixel_blend,
22614 wuffs_base__slice_u8,
22615 wuffs_base__decode_frame_options*))(&wuffs_bmp__decoder__decode_frame),
22616 (wuffs_base__status(*)(void*,
22617 wuffs_base__frame_config*,
22618 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_frame_config),
22619 (wuffs_base__status(*)(void*,
22620 wuffs_base__image_config*,
22621 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__decode_image_config),
22622 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_bmp__decoder__frame_dirty_rect),
22623 (uint32_t(*)(const void*))(&wuffs_bmp__decoder__num_animation_loops),
22624 (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frame_configs),
22625 (uint64_t(*)(const void*))(&wuffs_bmp__decoder__num_decoded_frames),
22626 (wuffs_base__status(*)(void*,
22627 uint64_t,
22628 uint64_t))(&wuffs_bmp__decoder__restart_frame),
22629 (wuffs_base__empty_struct(*)(void*,
22630 uint32_t,
22631 bool))(&wuffs_bmp__decoder__set_quirk_enabled),
22632 (wuffs_base__empty_struct(*)(void*,
22633 uint32_t,
22634 bool))(&wuffs_bmp__decoder__set_report_metadata),
22635 (wuffs_base__status(*)(void*,
22636 wuffs_base__io_buffer*,
22637 wuffs_base__more_information*,
22638 wuffs_base__io_buffer*))(&wuffs_bmp__decoder__tell_me_more),
22639 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bmp__decoder__workbuf_len),
22640};
22641
22642// ---------------- Initializer Implementations
22643
22644wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
22645wuffs_bmp__decoder__initialize(
22646 wuffs_bmp__decoder* self,
22647 size_t sizeof_star_self,
22648 uint64_t wuffs_version,
22649 uint32_t options){
22650 if (!self) {
22651 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
22652 }
22653 if (sizeof(*self) != sizeof_star_self) {
22654 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
22655 }
22656 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
22657 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
22658 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
22659 }
22660
22661 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
22662 // The whole point of this if-check is to detect an uninitialized *self.
22663 // We disable the warning on GCC. Clang-5.0 does not have this warning.
22664#if !defined(__clang__) && defined(__GNUC__)
22665#pragma GCC diagnostic push
22666#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
22667#endif
22668 if (self->private_impl.magic != 0) {
22669 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
22670 }
22671#if !defined(__clang__) && defined(__GNUC__)
22672#pragma GCC diagnostic pop
22673#endif
22674 } else {
22675 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
22676 memset(self, 0, sizeof(*self));
22677 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
22678 } else {
22679 memset(&(self->private_impl), 0, sizeof(self->private_impl));
22680 }
22681 }
22682
22683 self->private_impl.magic = WUFFS_BASE__MAGIC;
22684 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
22685 wuffs_base__image_decoder__vtable_name;
22686 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
22687 (const void*)(&wuffs_bmp__decoder__func_ptrs_for__wuffs_base__image_decoder);
22688 return wuffs_base__make_status(NULL);
22689}
22690
22691wuffs_bmp__decoder*
22692wuffs_bmp__decoder__alloc() {
22693 wuffs_bmp__decoder* x =
22694 (wuffs_bmp__decoder*)(calloc(sizeof(wuffs_bmp__decoder), 1));
22695 if (!x) {
22696 return NULL;
22697 }
22698 if (wuffs_bmp__decoder__initialize(
22699 x, sizeof(wuffs_bmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
22700 free(x);
22701 return NULL;
22702 }
22703 return x;
22704}
22705
22706size_t
22707sizeof__wuffs_bmp__decoder() {
22708 return sizeof(wuffs_bmp__decoder);
22709}
22710
22711// ---------------- Function Implementations
22712
22713// -------- func bmp.decoder.set_quirk_enabled
22714
22715WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
22716wuffs_bmp__decoder__set_quirk_enabled(
22717 wuffs_bmp__decoder* self,
22718 uint32_t a_quirk,
22719 bool a_enabled) {
22720 return wuffs_base__make_empty_struct();
22721}
22722
22723// -------- func bmp.decoder.decode_image_config
22724
22725WUFFS_BASE__MAYBE_STATIC wuffs_base__status
22726wuffs_bmp__decoder__decode_image_config(
22727 wuffs_bmp__decoder* self,
22728 wuffs_base__image_config* a_dst,
22729 wuffs_base__io_buffer* a_src) {
22730 if (!self) {
22731 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
22732 }
22733 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
22734 return wuffs_base__make_status(
22735 (self->private_impl.magic == WUFFS_BASE__DISABLED)
22736 ? wuffs_base__error__disabled_by_previous_error
22737 : wuffs_base__error__initialize_not_called);
22738 }
22739 if (!a_src) {
22740 self->private_impl.magic = WUFFS_BASE__DISABLED;
22741 return wuffs_base__make_status(wuffs_base__error__bad_argument);
22742 }
22743 if ((self->private_impl.active_coroutine != 0) &&
22744 (self->private_impl.active_coroutine != 1)) {
22745 self->private_impl.magic = WUFFS_BASE__DISABLED;
22746 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
22747 }
22748 self->private_impl.active_coroutine = 0;
22749 wuffs_base__status status = wuffs_base__make_status(NULL);
22750
22751 uint32_t v_magic = 0;
22752 uint32_t v_width = 0;
22753 uint32_t v_height = 0;
22754 uint32_t v_planes = 0;
22755 uint32_t v_dst_pixfmt = 0;
22756 uint32_t v_byte_width = 0;
22757
22758 const uint8_t* iop_a_src = NULL;
22759 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22760 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
22761 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110022762 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100022763 io0_a_src = a_src->data.ptr;
22764 io1_a_src = io0_a_src + a_src->meta.ri;
22765 iop_a_src = io1_a_src;
22766 io2_a_src = io0_a_src + a_src->meta.wi;
22767 }
22768
22769 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
22770 switch (coro_susp_point) {
22771 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
22772
22773 if ((self->private_impl.f_call_sequence != 0) || (self->private_impl.f_io_redirect_fourcc == 1)) {
22774 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
22775 goto exit;
22776 } else if (self->private_impl.f_io_redirect_fourcc != 0) {
22777 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
22778 goto ok;
22779 }
22780 {
22781 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
22782 uint32_t t_0;
22783 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22784 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22785 iop_a_src += 2;
22786 } else {
22787 self->private_data.s_decode_image_config[0].scratch = 0;
22788 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
22789 while (true) {
22790 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22791 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22792 goto suspend;
22793 }
22794 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22795 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
22796 *scratch <<= 8;
22797 *scratch >>= 8;
22798 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
22799 if (num_bits_0 == 8) {
22800 t_0 = ((uint32_t)(*scratch));
22801 break;
22802 }
22803 num_bits_0 += 8;
22804 *scratch |= ((uint64_t)(num_bits_0)) << 56;
22805 }
22806 }
22807 v_magic = t_0;
22808 }
22809 if (v_magic != 19778) {
22810 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22811 goto exit;
22812 }
22813 self->private_data.s_decode_image_config[0].scratch = 8;
22814 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
22815 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
22816 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
22817 iop_a_src = io2_a_src;
22818 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22819 goto suspend;
22820 }
22821 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
22822 {
22823 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
22824 uint32_t t_1;
22825 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22826 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22827 iop_a_src += 4;
22828 } else {
22829 self->private_data.s_decode_image_config[0].scratch = 0;
22830 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
22831 while (true) {
22832 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22833 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22834 goto suspend;
22835 }
22836 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22837 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
22838 *scratch <<= 8;
22839 *scratch >>= 8;
22840 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
22841 if (num_bits_1 == 24) {
22842 t_1 = ((uint32_t)(*scratch));
22843 break;
22844 }
22845 num_bits_1 += 8;
22846 *scratch |= ((uint64_t)(num_bits_1)) << 56;
22847 }
22848 }
22849 self->private_impl.f_padding = t_1;
22850 }
22851 if (self->private_impl.f_padding < 14) {
22852 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22853 goto exit;
22854 }
22855 self->private_impl.f_padding -= 14;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100022856 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 +100022857 {
22858 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
22859 uint32_t t_2;
22860 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
22861 t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
22862 iop_a_src += 4;
22863 } else {
22864 self->private_data.s_decode_image_config[0].scratch = 0;
22865 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
22866 while (true) {
22867 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22868 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22869 goto suspend;
22870 }
22871 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22872 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
22873 *scratch <<= 8;
22874 *scratch >>= 8;
22875 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
22876 if (num_bits_2 == 24) {
22877 t_2 = ((uint32_t)(*scratch));
22878 break;
22879 }
22880 num_bits_2 += 8;
22881 *scratch |= ((uint64_t)(num_bits_2)) << 56;
22882 }
22883 }
22884 self->private_impl.f_bitmap_info_len = t_2;
22885 }
22886 if (self->private_impl.f_padding < self->private_impl.f_bitmap_info_len) {
22887 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
22888 goto exit;
22889 }
22890 self->private_impl.f_padding -= self->private_impl.f_bitmap_info_len;
22891 if (self->private_impl.f_bitmap_info_len == 12) {
22892 {
22893 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
22894 uint32_t t_3;
22895 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22896 t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22897 iop_a_src += 2;
22898 } else {
22899 self->private_data.s_decode_image_config[0].scratch = 0;
22900 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
22901 while (true) {
22902 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22903 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22904 goto suspend;
22905 }
22906 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22907 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
22908 *scratch <<= 8;
22909 *scratch >>= 8;
22910 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
22911 if (num_bits_3 == 8) {
22912 t_3 = ((uint32_t)(*scratch));
22913 break;
22914 }
22915 num_bits_3 += 8;
22916 *scratch |= ((uint64_t)(num_bits_3)) << 56;
22917 }
22918 }
22919 self->private_impl.f_width = t_3;
22920 }
22921 {
22922 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
22923 uint32_t t_4;
22924 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22925 t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22926 iop_a_src += 2;
22927 } else {
22928 self->private_data.s_decode_image_config[0].scratch = 0;
22929 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
22930 while (true) {
22931 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22932 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22933 goto suspend;
22934 }
22935 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22936 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
22937 *scratch <<= 8;
22938 *scratch >>= 8;
22939 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
22940 if (num_bits_4 == 8) {
22941 t_4 = ((uint32_t)(*scratch));
22942 break;
22943 }
22944 num_bits_4 += 8;
22945 *scratch |= ((uint64_t)(num_bits_4)) << 56;
22946 }
22947 }
22948 self->private_impl.f_height = t_4;
22949 }
22950 {
22951 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
22952 uint32_t t_5;
22953 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22954 t_5 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22955 iop_a_src += 2;
22956 } else {
22957 self->private_data.s_decode_image_config[0].scratch = 0;
22958 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
22959 while (true) {
22960 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22961 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22962 goto suspend;
22963 }
22964 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22965 uint32_t num_bits_5 = ((uint32_t)(*scratch >> 56));
22966 *scratch <<= 8;
22967 *scratch >>= 8;
22968 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_5;
22969 if (num_bits_5 == 8) {
22970 t_5 = ((uint32_t)(*scratch));
22971 break;
22972 }
22973 num_bits_5 += 8;
22974 *scratch |= ((uint64_t)(num_bits_5)) << 56;
22975 }
22976 }
22977 v_planes = t_5;
22978 }
22979 if (v_planes != 1) {
22980 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
22981 goto exit;
22982 }
22983 {
22984 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
22985 uint32_t t_6;
22986 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
22987 t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
22988 iop_a_src += 2;
22989 } else {
22990 self->private_data.s_decode_image_config[0].scratch = 0;
22991 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
22992 while (true) {
22993 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
22994 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
22995 goto suspend;
22996 }
22997 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
22998 uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56));
22999 *scratch <<= 8;
23000 *scratch >>= 8;
23001 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6;
23002 if (num_bits_6 == 8) {
23003 t_6 = ((uint32_t)(*scratch));
23004 break;
23005 }
23006 num_bits_6 += 8;
23007 *scratch |= ((uint64_t)(num_bits_6)) << 56;
23008 }
23009 }
23010 self->private_impl.f_bits_per_pixel = t_6;
23011 }
23012 } else if (self->private_impl.f_bitmap_info_len == 16) {
23013 {
23014 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
23015 uint32_t t_7;
23016 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23017 t_7 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23018 iop_a_src += 4;
23019 } else {
23020 self->private_data.s_decode_image_config[0].scratch = 0;
23021 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
23022 while (true) {
23023 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23024 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23025 goto suspend;
23026 }
23027 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23028 uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56));
23029 *scratch <<= 8;
23030 *scratch >>= 8;
23031 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7;
23032 if (num_bits_7 == 24) {
23033 t_7 = ((uint32_t)(*scratch));
23034 break;
23035 }
23036 num_bits_7 += 8;
23037 *scratch |= ((uint64_t)(num_bits_7)) << 56;
23038 }
23039 }
23040 v_width = t_7;
23041 }
23042 if (v_width >= 2147483648) {
23043 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
23044 goto exit;
23045 }
23046 self->private_impl.f_width = v_width;
23047 {
23048 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18);
23049 uint32_t t_8;
23050 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23051 t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23052 iop_a_src += 4;
23053 } else {
23054 self->private_data.s_decode_image_config[0].scratch = 0;
23055 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19);
23056 while (true) {
23057 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23058 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23059 goto suspend;
23060 }
23061 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23062 uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
23063 *scratch <<= 8;
23064 *scratch >>= 8;
23065 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
23066 if (num_bits_8 == 24) {
23067 t_8 = ((uint32_t)(*scratch));
23068 break;
23069 }
23070 num_bits_8 += 8;
23071 *scratch |= ((uint64_t)(num_bits_8)) << 56;
23072 }
23073 }
23074 v_height = t_8;
23075 }
23076 if (v_height >= 2147483648) {
23077 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
23078 goto exit;
23079 }
23080 self->private_impl.f_height = v_height;
23081 {
23082 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20);
23083 uint32_t t_9;
23084 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
23085 t_9 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
23086 iop_a_src += 2;
23087 } else {
23088 self->private_data.s_decode_image_config[0].scratch = 0;
23089 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21);
23090 while (true) {
23091 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23092 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23093 goto suspend;
23094 }
23095 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23096 uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
23097 *scratch <<= 8;
23098 *scratch >>= 8;
23099 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
23100 if (num_bits_9 == 8) {
23101 t_9 = ((uint32_t)(*scratch));
23102 break;
23103 }
23104 num_bits_9 += 8;
23105 *scratch |= ((uint64_t)(num_bits_9)) << 56;
23106 }
23107 }
23108 v_planes = t_9;
23109 }
23110 if (v_planes != 1) {
23111 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23112 goto exit;
23113 }
23114 {
23115 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
23116 uint32_t t_10;
23117 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
23118 t_10 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
23119 iop_a_src += 2;
23120 } else {
23121 self->private_data.s_decode_image_config[0].scratch = 0;
23122 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
23123 while (true) {
23124 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23125 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23126 goto suspend;
23127 }
23128 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23129 uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56));
23130 *scratch <<= 8;
23131 *scratch >>= 8;
23132 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10;
23133 if (num_bits_10 == 8) {
23134 t_10 = ((uint32_t)(*scratch));
23135 break;
23136 }
23137 num_bits_10 += 8;
23138 *scratch |= ((uint64_t)(num_bits_10)) << 56;
23139 }
23140 }
23141 self->private_impl.f_bits_per_pixel = t_10;
23142 }
23143 } else {
23144 {
23145 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
23146 uint32_t t_11;
23147 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23148 t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23149 iop_a_src += 4;
23150 } else {
23151 self->private_data.s_decode_image_config[0].scratch = 0;
23152 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(25);
23153 while (true) {
23154 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23155 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23156 goto suspend;
23157 }
23158 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23159 uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56));
23160 *scratch <<= 8;
23161 *scratch >>= 8;
23162 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11;
23163 if (num_bits_11 == 24) {
23164 t_11 = ((uint32_t)(*scratch));
23165 break;
23166 }
23167 num_bits_11 += 8;
23168 *scratch |= ((uint64_t)(num_bits_11)) << 56;
23169 }
23170 }
23171 v_width = t_11;
23172 }
23173 if (v_width >= 2147483648) {
23174 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
23175 goto exit;
23176 }
23177 self->private_impl.f_width = v_width;
23178 {
23179 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(26);
23180 uint32_t t_12;
23181 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23182 t_12 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23183 iop_a_src += 4;
23184 } else {
23185 self->private_data.s_decode_image_config[0].scratch = 0;
23186 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(27);
23187 while (true) {
23188 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23189 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23190 goto suspend;
23191 }
23192 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23193 uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56));
23194 *scratch <<= 8;
23195 *scratch >>= 8;
23196 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12;
23197 if (num_bits_12 == 24) {
23198 t_12 = ((uint32_t)(*scratch));
23199 break;
23200 }
23201 num_bits_12 += 8;
23202 *scratch |= ((uint64_t)(num_bits_12)) << 56;
23203 }
23204 }
23205 v_height = t_12;
23206 }
23207 if (v_height == 2147483648) {
23208 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
23209 goto exit;
23210 } else if (v_height >= 2147483648) {
23211 self->private_impl.f_height = (((uint32_t)(0 - v_height)) & 2147483647);
23212 self->private_impl.f_top_down = true;
23213 } else {
23214 self->private_impl.f_height = v_height;
23215 }
23216 {
23217 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(28);
23218 uint32_t t_13;
23219 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
23220 t_13 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
23221 iop_a_src += 2;
23222 } else {
23223 self->private_data.s_decode_image_config[0].scratch = 0;
23224 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(29);
23225 while (true) {
23226 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23227 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23228 goto suspend;
23229 }
23230 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23231 uint32_t num_bits_13 = ((uint32_t)(*scratch >> 56));
23232 *scratch <<= 8;
23233 *scratch >>= 8;
23234 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_13;
23235 if (num_bits_13 == 8) {
23236 t_13 = ((uint32_t)(*scratch));
23237 break;
23238 }
23239 num_bits_13 += 8;
23240 *scratch |= ((uint64_t)(num_bits_13)) << 56;
23241 }
23242 }
23243 v_planes = t_13;
23244 }
23245 if (v_planes != 1) {
23246 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23247 goto exit;
23248 }
23249 {
23250 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(30);
23251 uint32_t t_14;
23252 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
23253 t_14 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
23254 iop_a_src += 2;
23255 } else {
23256 self->private_data.s_decode_image_config[0].scratch = 0;
23257 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(31);
23258 while (true) {
23259 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23260 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23261 goto suspend;
23262 }
23263 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23264 uint32_t num_bits_14 = ((uint32_t)(*scratch >> 56));
23265 *scratch <<= 8;
23266 *scratch >>= 8;
23267 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_14;
23268 if (num_bits_14 == 8) {
23269 t_14 = ((uint32_t)(*scratch));
23270 break;
23271 }
23272 num_bits_14 += 8;
23273 *scratch |= ((uint64_t)(num_bits_14)) << 56;
23274 }
23275 }
23276 self->private_impl.f_bits_per_pixel = t_14;
23277 }
23278 {
23279 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(32);
23280 uint32_t t_15;
23281 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23282 t_15 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23283 iop_a_src += 4;
23284 } else {
23285 self->private_data.s_decode_image_config[0].scratch = 0;
23286 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(33);
23287 while (true) {
23288 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23289 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23290 goto suspend;
23291 }
23292 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23293 uint32_t num_bits_15 = ((uint32_t)(*scratch >> 56));
23294 *scratch <<= 8;
23295 *scratch >>= 8;
23296 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_15;
23297 if (num_bits_15 == 24) {
23298 t_15 = ((uint32_t)(*scratch));
23299 break;
23300 }
23301 num_bits_15 += 8;
23302 *scratch |= ((uint64_t)(num_bits_15)) << 56;
23303 }
23304 }
23305 self->private_impl.f_compression = t_15;
23306 }
23307 if (self->private_impl.f_bits_per_pixel == 0) {
23308 if (self->private_impl.f_compression == 4) {
23309 self->private_impl.f_io_redirect_fourcc = 1246774599;
23310 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
23311 goto ok;
23312 } else if (self->private_impl.f_compression == 5) {
23313 self->private_impl.f_io_redirect_fourcc = 1347307296;
23314 status = wuffs_base__make_status(wuffs_base__note__i_o_redirect);
23315 goto ok;
23316 }
23317 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23318 goto exit;
23319 }
23320 self->private_data.s_decode_image_config[0].scratch = 20;
23321 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(34);
23322 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
23323 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
23324 iop_a_src = io2_a_src;
23325 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23326 goto suspend;
23327 }
23328 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
23329 if (self->private_impl.f_bitmap_info_len == 40) {
23330 if (self->private_impl.f_bits_per_pixel >= 16) {
23331 if (self->private_impl.f_padding >= 16) {
23332 self->private_impl.f_bitmap_info_len = 56;
23333 self->private_impl.f_padding -= 16;
23334 } else if (self->private_impl.f_padding >= 12) {
23335 self->private_impl.f_bitmap_info_len = 52;
23336 self->private_impl.f_padding -= 12;
23337 }
23338 }
23339 } else if ((self->private_impl.f_bitmap_info_len != 52) &&
23340 (self->private_impl.f_bitmap_info_len != 56) &&
23341 (self->private_impl.f_bitmap_info_len != 64) &&
23342 (self->private_impl.f_bitmap_info_len != 108) &&
23343 (self->private_impl.f_bitmap_info_len != 124)) {
23344 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23345 goto exit;
23346 }
23347 if (self->private_impl.f_compression == 6) {
23348 self->private_impl.f_compression = 3;
23349 }
23350 if (self->private_impl.f_compression == 3) {
23351 if (self->private_impl.f_bitmap_info_len >= 52) {
23352 {
23353 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(35);
23354 uint32_t t_16;
23355 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23356 t_16 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23357 iop_a_src += 4;
23358 } else {
23359 self->private_data.s_decode_image_config[0].scratch = 0;
23360 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(36);
23361 while (true) {
23362 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23363 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23364 goto suspend;
23365 }
23366 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23367 uint32_t num_bits_16 = ((uint32_t)(*scratch >> 56));
23368 *scratch <<= 8;
23369 *scratch >>= 8;
23370 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_16;
23371 if (num_bits_16 == 24) {
23372 t_16 = ((uint32_t)(*scratch));
23373 break;
23374 }
23375 num_bits_16 += 8;
23376 *scratch |= ((uint64_t)(num_bits_16)) << 56;
23377 }
23378 }
23379 self->private_impl.f_channel_masks[2] = t_16;
23380 }
23381 {
23382 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(37);
23383 uint32_t t_17;
23384 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23385 t_17 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23386 iop_a_src += 4;
23387 } else {
23388 self->private_data.s_decode_image_config[0].scratch = 0;
23389 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(38);
23390 while (true) {
23391 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23392 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23393 goto suspend;
23394 }
23395 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23396 uint32_t num_bits_17 = ((uint32_t)(*scratch >> 56));
23397 *scratch <<= 8;
23398 *scratch >>= 8;
23399 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_17;
23400 if (num_bits_17 == 24) {
23401 t_17 = ((uint32_t)(*scratch));
23402 break;
23403 }
23404 num_bits_17 += 8;
23405 *scratch |= ((uint64_t)(num_bits_17)) << 56;
23406 }
23407 }
23408 self->private_impl.f_channel_masks[1] = t_17;
23409 }
23410 {
23411 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(39);
23412 uint32_t t_18;
23413 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23414 t_18 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23415 iop_a_src += 4;
23416 } else {
23417 self->private_data.s_decode_image_config[0].scratch = 0;
23418 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(40);
23419 while (true) {
23420 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23421 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23422 goto suspend;
23423 }
23424 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23425 uint32_t num_bits_18 = ((uint32_t)(*scratch >> 56));
23426 *scratch <<= 8;
23427 *scratch >>= 8;
23428 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_18;
23429 if (num_bits_18 == 24) {
23430 t_18 = ((uint32_t)(*scratch));
23431 break;
23432 }
23433 num_bits_18 += 8;
23434 *scratch |= ((uint64_t)(num_bits_18)) << 56;
23435 }
23436 }
23437 self->private_impl.f_channel_masks[0] = t_18;
23438 }
23439 if (self->private_impl.f_bitmap_info_len >= 56) {
23440 {
23441 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(41);
23442 uint32_t t_19;
23443 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
23444 t_19 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
23445 iop_a_src += 4;
23446 } else {
23447 self->private_data.s_decode_image_config[0].scratch = 0;
23448 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(42);
23449 while (true) {
23450 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
23451 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23452 goto suspend;
23453 }
23454 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
23455 uint32_t num_bits_19 = ((uint32_t)(*scratch >> 56));
23456 *scratch <<= 8;
23457 *scratch >>= 8;
23458 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_19;
23459 if (num_bits_19 == 24) {
23460 t_19 = ((uint32_t)(*scratch));
23461 break;
23462 }
23463 num_bits_19 += 8;
23464 *scratch |= ((uint64_t)(num_bits_19)) << 56;
23465 }
23466 }
23467 self->private_impl.f_channel_masks[3] = t_19;
23468 }
23469 self->private_data.s_decode_image_config[0].scratch = ((uint32_t)(self->private_impl.f_bitmap_info_len - 56));
23470 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(43);
23471 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
23472 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
23473 iop_a_src = io2_a_src;
23474 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23475 goto suspend;
23476 }
23477 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
23478 }
23479 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)) {
23480 if (self->private_impl.f_bits_per_pixel == 24) {
23481 self->private_impl.f_compression = 0;
23482 } else if (self->private_impl.f_bits_per_pixel == 32) {
23483 if ((self->private_impl.f_channel_masks[3] == 0) || (self->private_impl.f_channel_masks[3] == 4278190080)) {
23484 self->private_impl.f_compression = 0;
23485 }
23486 }
23487 }
23488 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(44);
23489 status = wuffs_bmp__decoder__process_masks(self);
23490 if (status.repr) {
23491 goto suspend;
23492 }
23493 }
23494 } else if (self->private_impl.f_bitmap_info_len >= 40) {
23495 self->private_data.s_decode_image_config[0].scratch = (self->private_impl.f_bitmap_info_len - 40);
23496 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(45);
23497 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
23498 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
23499 iop_a_src = io2_a_src;
23500 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23501 goto suspend;
23502 }
23503 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
23504 } else {
23505 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23506 goto exit;
23507 }
23508 }
23509 if (self->private_impl.f_compression != 3) {
23510 if (self->private_impl.f_bits_per_pixel < 16) {
23511 if (a_src) {
23512 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23513 }
23514 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(46);
23515 status = wuffs_bmp__decoder__read_palette(self, a_src);
23516 if (a_src) {
23517 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23518 }
23519 if (status.repr) {
23520 goto suspend;
23521 }
23522 }
23523 }
23524 if (self->private_impl.f_compression == 0) {
23525 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)) {
23526 self->private_impl.f_src_pixfmt = 2198077448;
23527 self->private_impl.f_compression = 256;
23528 } else if (self->private_impl.f_bits_per_pixel == 8) {
23529 self->private_impl.f_src_pixfmt = 2198077448;
23530 } else if (self->private_impl.f_bits_per_pixel == 16) {
23531 self->private_impl.f_compression = 3;
23532 self->private_impl.f_channel_masks[0] = 31;
23533 self->private_impl.f_channel_masks[1] = 992;
23534 self->private_impl.f_channel_masks[2] = 31744;
23535 self->private_impl.f_channel_masks[3] = 0;
23536 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(47);
23537 status = wuffs_bmp__decoder__process_masks(self);
23538 if (status.repr) {
23539 goto suspend;
23540 }
23541 self->private_impl.f_src_pixfmt = 2164308923;
23542 } else if (self->private_impl.f_bits_per_pixel == 24) {
23543 self->private_impl.f_src_pixfmt = 2147485832;
23544 } else if (self->private_impl.f_bits_per_pixel == 32) {
23545 if (self->private_impl.f_channel_masks[3] == 0) {
23546 self->private_impl.f_src_pixfmt = 2415954056;
23547 } else {
23548 self->private_impl.f_src_pixfmt = 2164295816;
23549 }
23550 } else {
23551 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23552 goto exit;
23553 }
23554 } else if (self->private_impl.f_compression == 1) {
23555 if (self->private_impl.f_bits_per_pixel == 8) {
23556 self->private_impl.f_src_pixfmt = 2198077448;
23557 } else {
23558 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23559 goto exit;
23560 }
23561 } else if (self->private_impl.f_compression == 2) {
23562 if (self->private_impl.f_bits_per_pixel == 4) {
23563 self->private_impl.f_src_pixfmt = 2198077448;
23564 } else {
23565 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23566 goto exit;
23567 }
23568 } else if (self->private_impl.f_compression == 3) {
23569 if ((self->private_impl.f_bits_per_pixel == 16) || (self->private_impl.f_bits_per_pixel == 32)) {
23570 self->private_impl.f_src_pixfmt = 2164308923;
23571 } else {
23572 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23573 goto exit;
23574 }
23575 } else {
23576 status = wuffs_base__make_status(wuffs_bmp__error__unsupported_bmp_file);
23577 goto exit;
23578 }
23579 if (((self->private_impl.f_bitmap_info_len < 40) || (self->private_impl.f_bitmap_info_len == 64)) &&
23580 (self->private_impl.f_bits_per_pixel != 1) &&
23581 (self->private_impl.f_bits_per_pixel != 4) &&
23582 (self->private_impl.f_bits_per_pixel != 8) &&
23583 (self->private_impl.f_bits_per_pixel != 24)) {
23584 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
23585 goto exit;
23586 }
23587 if (self->private_impl.f_bits_per_pixel == 1) {
23588 v_byte_width = ((self->private_impl.f_width >> 3) + (((self->private_impl.f_width & 7) + 7) >> 3));
23589 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
23590 } else if (self->private_impl.f_bits_per_pixel == 2) {
23591 v_byte_width = ((self->private_impl.f_width >> 2) + (((self->private_impl.f_width & 3) + 3) >> 2));
23592 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
23593 } else if (self->private_impl.f_bits_per_pixel == 4) {
23594 v_byte_width = ((self->private_impl.f_width >> 1) + (self->private_impl.f_width & 1));
23595 self->private_impl.f_pad_per_row = ((4 - (v_byte_width & 3)) & 3);
23596 } else if (self->private_impl.f_bits_per_pixel == 8) {
23597 self->private_impl.f_pad_per_row = ((4 - (self->private_impl.f_width & 3)) & 3);
23598 } else if (self->private_impl.f_bits_per_pixel == 16) {
23599 self->private_impl.f_pad_per_row = ((self->private_impl.f_width & 1) * 2);
23600 } else if (self->private_impl.f_bits_per_pixel == 24) {
23601 self->private_impl.f_pad_per_row = (self->private_impl.f_width & 3);
23602 } else if (self->private_impl.f_bits_per_pixel == 32) {
23603 self->private_impl.f_pad_per_row = 0;
23604 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100023605 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 +100023606 if (a_dst != NULL) {
23607 v_dst_pixfmt = 2164295816;
23608 if ((self->private_impl.f_channel_num_bits[0] > 8) ||
23609 (self->private_impl.f_channel_num_bits[1] > 8) ||
23610 (self->private_impl.f_channel_num_bits[2] > 8) ||
23611 (self->private_impl.f_channel_num_bits[3] > 8)) {
23612 v_dst_pixfmt = 2164308923;
23613 }
23614 wuffs_base__image_config__set(
23615 a_dst,
23616 v_dst_pixfmt,
23617 0,
23618 self->private_impl.f_width,
23619 self->private_impl.f_height,
23620 self->private_impl.f_frame_config_io_position,
23621 (self->private_impl.f_channel_masks[3] == 0));
23622 }
Nigel Tao123a5c62022-06-03 14:17:20 +100023623 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100023624
Nigel Taoe360a532021-04-05 22:47:03 +100023625 ok:
23626 self->private_impl.p_decode_image_config[0] = 0;
23627 goto exit;
23628 }
23629
23630 goto suspend;
23631 suspend:
23632 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
23633 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
23634
23635 goto exit;
23636 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110023637 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023638 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23639 }
23640
23641 if (wuffs_base__status__is_error(&status)) {
23642 self->private_impl.magic = WUFFS_BASE__DISABLED;
23643 }
23644 return status;
23645}
23646
23647// -------- func bmp.decoder.decode_frame_config
23648
23649WUFFS_BASE__MAYBE_STATIC wuffs_base__status
23650wuffs_bmp__decoder__decode_frame_config(
23651 wuffs_bmp__decoder* self,
23652 wuffs_base__frame_config* a_dst,
23653 wuffs_base__io_buffer* a_src) {
23654 if (!self) {
23655 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
23656 }
23657 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
23658 return wuffs_base__make_status(
23659 (self->private_impl.magic == WUFFS_BASE__DISABLED)
23660 ? wuffs_base__error__disabled_by_previous_error
23661 : wuffs_base__error__initialize_not_called);
23662 }
23663 if (!a_src) {
23664 self->private_impl.magic = WUFFS_BASE__DISABLED;
23665 return wuffs_base__make_status(wuffs_base__error__bad_argument);
23666 }
23667 if ((self->private_impl.active_coroutine != 0) &&
23668 (self->private_impl.active_coroutine != 2)) {
23669 self->private_impl.magic = WUFFS_BASE__DISABLED;
23670 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
23671 }
23672 self->private_impl.active_coroutine = 0;
23673 wuffs_base__status status = wuffs_base__make_status(NULL);
23674
23675 const uint8_t* iop_a_src = NULL;
23676 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23677 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23678 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110023679 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023680 io0_a_src = a_src->data.ptr;
23681 io1_a_src = io0_a_src + a_src->meta.ri;
23682 iop_a_src = io1_a_src;
23683 io2_a_src = io0_a_src + a_src->meta.wi;
23684 }
23685
23686 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
23687 switch (coro_susp_point) {
23688 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
23689
Nigel Tao123a5c62022-06-03 14:17:20 +100023690 if (self->private_impl.f_call_sequence == 32) {
23691 } else if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100023692 if (a_src) {
23693 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23694 }
23695 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
23696 status = wuffs_bmp__decoder__decode_image_config(self, NULL, a_src);
23697 if (a_src) {
23698 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23699 }
23700 if (status.repr) {
23701 goto suspend;
23702 }
Nigel Tao123a5c62022-06-03 14:17:20 +100023703 } else if (self->private_impl.f_call_sequence == 40) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100023704 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 +100023705 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
23706 goto exit;
23707 }
Nigel Tao123a5c62022-06-03 14:17:20 +100023708 } else if (self->private_impl.f_call_sequence == 64) {
23709 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100023710 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
23711 goto ok;
23712 } else {
23713 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
23714 goto ok;
23715 }
23716 if (a_dst != NULL) {
23717 wuffs_base__frame_config__set(
23718 a_dst,
23719 wuffs_base__utility__make_rect_ie_u32(
23720 0,
23721 0,
23722 self->private_impl.f_width,
23723 self->private_impl.f_height),
23724 ((wuffs_base__flicks)(0)),
23725 0,
23726 self->private_impl.f_frame_config_io_position,
23727 0,
23728 true,
23729 false,
23730 4278190080);
23731 }
Nigel Tao123a5c62022-06-03 14:17:20 +100023732 self->private_impl.f_call_sequence = 64;
Nigel Taoe360a532021-04-05 22:47:03 +100023733
Nigel Taoe360a532021-04-05 22:47:03 +100023734 ok:
23735 self->private_impl.p_decode_frame_config[0] = 0;
23736 goto exit;
23737 }
23738
23739 goto suspend;
23740 suspend:
23741 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
23742 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
23743
23744 goto exit;
23745 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110023746 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023747 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23748 }
23749
23750 if (wuffs_base__status__is_error(&status)) {
23751 self->private_impl.magic = WUFFS_BASE__DISABLED;
23752 }
23753 return status;
23754}
23755
23756// -------- func bmp.decoder.decode_frame
23757
23758WUFFS_BASE__MAYBE_STATIC wuffs_base__status
23759wuffs_bmp__decoder__decode_frame(
23760 wuffs_bmp__decoder* self,
23761 wuffs_base__pixel_buffer* a_dst,
23762 wuffs_base__io_buffer* a_src,
23763 wuffs_base__pixel_blend a_blend,
23764 wuffs_base__slice_u8 a_workbuf,
23765 wuffs_base__decode_frame_options* a_opts) {
23766 if (!self) {
23767 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
23768 }
23769 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
23770 return wuffs_base__make_status(
23771 (self->private_impl.magic == WUFFS_BASE__DISABLED)
23772 ? wuffs_base__error__disabled_by_previous_error
23773 : wuffs_base__error__initialize_not_called);
23774 }
23775 if (!a_dst || !a_src) {
23776 self->private_impl.magic = WUFFS_BASE__DISABLED;
23777 return wuffs_base__make_status(wuffs_base__error__bad_argument);
23778 }
23779 if ((self->private_impl.active_coroutine != 0) &&
23780 (self->private_impl.active_coroutine != 3)) {
23781 self->private_impl.magic = WUFFS_BASE__DISABLED;
23782 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
23783 }
23784 self->private_impl.active_coroutine = 0;
23785 wuffs_base__status status = wuffs_base__make_status(NULL);
23786
23787 wuffs_base__status v_status = wuffs_base__make_status(NULL);
23788
23789 const uint8_t* iop_a_src = NULL;
23790 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23791 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23792 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110023793 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023794 io0_a_src = a_src->data.ptr;
23795 io1_a_src = io0_a_src + a_src->meta.ri;
23796 iop_a_src = io1_a_src;
23797 io2_a_src = io0_a_src + a_src->meta.wi;
23798 }
23799
23800 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
Nigel Taoe360a532021-04-05 22:47:03 +100023801 switch (coro_susp_point) {
23802 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
23803
Nigel Tao123a5c62022-06-03 14:17:20 +100023804 if (self->private_impl.f_call_sequence == 64) {
23805 } else if (self->private_impl.f_call_sequence < 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100023806 if (a_src) {
23807 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23808 }
23809 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
23810 status = wuffs_bmp__decoder__decode_frame_config(self, NULL, a_src);
23811 if (a_src) {
23812 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23813 }
23814 if (status.repr) {
23815 goto suspend;
23816 }
Nigel Taoe360a532021-04-05 22:47:03 +100023817 } else {
23818 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
23819 goto ok;
23820 }
23821 self->private_data.s_decode_frame[0].scratch = self->private_impl.f_padding;
23822 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
23823 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
23824 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
23825 iop_a_src = io2_a_src;
23826 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23827 goto suspend;
23828 }
23829 iop_a_src += self->private_data.s_decode_frame[0].scratch;
23830 if ((self->private_impl.f_width > 0) && (self->private_impl.f_height > 0)) {
23831 self->private_impl.f_dst_x = 0;
23832 if (self->private_impl.f_top_down) {
23833 self->private_impl.f_dst_y = 0;
23834 self->private_impl.f_dst_y_inc = 1;
23835 } else {
23836 self->private_impl.f_dst_y = ((uint32_t)(self->private_impl.f_height - 1));
23837 self->private_impl.f_dst_y_inc = 4294967295;
23838 }
23839 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
23840 wuffs_base__pixel_buffer__pixel_format(a_dst),
Nigel Tao123a5c62022-06-03 14:17:20 +100023841 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048)),
Nigel Taoe360a532021-04-05 22:47:03 +100023842 wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt),
23843 wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024),
23844 a_blend);
23845 if ( ! wuffs_base__status__is_ok(&v_status)) {
23846 status = v_status;
23847 if (wuffs_base__status__is_error(&status)) {
23848 goto exit;
23849 } else if (wuffs_base__status__is_suspension(&status)) {
23850 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
23851 goto exit;
23852 }
23853 goto ok;
23854 }
23855 while (true) {
23856 if (self->private_impl.f_compression == 0) {
23857 if (a_src) {
23858 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23859 }
23860 v_status = wuffs_bmp__decoder__swizzle_none(self, a_dst, a_src);
23861 if (a_src) {
23862 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23863 }
23864 } else if (self->private_impl.f_compression < 3) {
23865 if (a_src) {
23866 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23867 }
23868 v_status = wuffs_bmp__decoder__swizzle_rle(self, a_dst, a_src);
23869 if (a_src) {
23870 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23871 }
23872 } else if (self->private_impl.f_compression == 3) {
23873 if (a_src) {
23874 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23875 }
23876 v_status = wuffs_bmp__decoder__swizzle_bitfields(self, a_dst, a_src);
23877 if (a_src) {
23878 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23879 }
23880 } else {
23881 if (a_src) {
23882 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23883 }
23884 v_status = wuffs_bmp__decoder__swizzle_low_bit_depth(self, a_dst, a_src);
23885 if (a_src) {
23886 iop_a_src = a_src->data.ptr + a_src->meta.ri;
23887 }
23888 }
23889 if (wuffs_base__status__is_ok(&v_status)) {
23890 goto label__0__break;
23891 } else if (v_status.repr != wuffs_bmp__note__internal_note_short_read) {
23892 status = v_status;
23893 if (wuffs_base__status__is_error(&status)) {
23894 goto exit;
23895 } else if (wuffs_base__status__is_suspension(&status)) {
23896 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
23897 goto exit;
23898 }
23899 goto ok;
23900 }
23901 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23902 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
23903 }
23904 label__0__break:;
23905 self->private_data.s_decode_frame[0].scratch = self->private_impl.f_pending_pad;
23906 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
23907 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
23908 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
23909 iop_a_src = io2_a_src;
23910 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
23911 goto suspend;
23912 }
23913 iop_a_src += self->private_data.s_decode_frame[0].scratch;
23914 self->private_impl.f_pending_pad = 0;
23915 }
Nigel Tao123a5c62022-06-03 14:17:20 +100023916 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100023917
Nigel Taoe360a532021-04-05 22:47:03 +100023918 ok:
23919 self->private_impl.p_decode_frame[0] = 0;
23920 goto exit;
23921 }
23922
23923 goto suspend;
23924 suspend:
23925 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
23926 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100023927
23928 goto exit;
23929 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110023930 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023931 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
23932 }
23933
23934 if (wuffs_base__status__is_error(&status)) {
23935 self->private_impl.magic = WUFFS_BASE__DISABLED;
23936 }
23937 return status;
23938}
23939
23940// -------- func bmp.decoder.swizzle_none
23941
23942static wuffs_base__status
23943wuffs_bmp__decoder__swizzle_none(
23944 wuffs_bmp__decoder* self,
23945 wuffs_base__pixel_buffer* a_dst,
23946 wuffs_base__io_buffer* a_src) {
23947 wuffs_base__status status = wuffs_base__make_status(NULL);
23948
23949 wuffs_base__pixel_format v_dst_pixfmt = {0};
23950 uint32_t v_dst_bits_per_pixel = 0;
23951 uint64_t v_dst_bytes_per_pixel = 0;
23952 uint64_t v_dst_bytes_per_row = 0;
23953 wuffs_base__slice_u8 v_dst_palette = {0};
23954 wuffs_base__table_u8 v_tab = {0};
23955 wuffs_base__slice_u8 v_dst = {0};
23956 uint64_t v_i = 0;
23957 uint64_t v_n = 0;
23958
23959 const uint8_t* iop_a_src = NULL;
23960 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23961 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
23962 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110023963 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100023964 io0_a_src = a_src->data.ptr;
23965 io1_a_src = io0_a_src + a_src->meta.ri;
23966 iop_a_src = io1_a_src;
23967 io2_a_src = io0_a_src + a_src->meta.wi;
23968 }
23969
23970 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
23971 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
23972 if ((v_dst_bits_per_pixel & 7) != 0) {
23973 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
23974 goto exit;
23975 }
23976 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
23977 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
Nigel Tao123a5c62022-06-03 14:17:20 +100023978 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048));
Nigel Taoe360a532021-04-05 22:47:03 +100023979 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
23980 label__outer__continue:;
23981 while (true) {
23982 while (self->private_impl.f_pending_pad > 0) {
23983 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
23984 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
23985 goto ok;
23986 }
23987 self->private_impl.f_pending_pad -= 1;
23988 iop_a_src += 1;
23989 }
23990 label__inner__continue:;
23991 while (true) {
23992 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
23993 self->private_impl.f_dst_x = 0;
23994 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
23995 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
23996 if (self->private_impl.f_height > 0) {
23997 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
23998 }
23999 goto label__outer__break;
24000 } else if (self->private_impl.f_pad_per_row != 0) {
24001 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
24002 goto label__outer__continue;
24003 }
24004 }
Nigel Taobf9dab32021-11-18 19:19:55 +110024005 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024006 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
24007 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
24008 }
24009 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
24010 if (v_i >= ((uint64_t)(v_dst.len))) {
24011 goto label__inner__continue;
24012 }
24013 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
24014 &self->private_impl.f_swizzler,
24015 wuffs_base__slice_u8__subslice_i(v_dst, v_i),
24016 v_dst_palette,
24017 &iop_a_src,
24018 io2_a_src);
24019 if (v_n == 0) {
24020 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
24021 goto ok;
24022 }
24023 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
24024 }
24025 }
24026 label__outer__break:;
24027 status = wuffs_base__make_status(NULL);
24028 goto ok;
24029
Nigel Taoe360a532021-04-05 22:47:03 +100024030 ok:
24031 goto exit;
24032 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110024033 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024034 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24035 }
24036
24037 return status;
24038}
24039
24040// -------- func bmp.decoder.swizzle_rle
24041
24042static wuffs_base__status
24043wuffs_bmp__decoder__swizzle_rle(
24044 wuffs_bmp__decoder* self,
24045 wuffs_base__pixel_buffer* a_dst,
24046 wuffs_base__io_buffer* a_src) {
24047 wuffs_base__status status = wuffs_base__make_status(NULL);
24048
24049 wuffs_base__pixel_format v_dst_pixfmt = {0};
24050 uint32_t v_dst_bits_per_pixel = 0;
24051 uint64_t v_dst_bytes_per_pixel = 0;
24052 uint64_t v_dst_bytes_per_row = 0;
24053 wuffs_base__slice_u8 v_dst_palette = {0};
24054 wuffs_base__table_u8 v_tab = {0};
24055 wuffs_base__slice_u8 v_row = {0};
24056 wuffs_base__slice_u8 v_dst = {0};
24057 uint64_t v_i = 0;
24058 uint64_t v_n = 0;
24059 uint32_t v_p0 = 0;
24060 uint8_t v_code = 0;
24061 uint8_t v_indexes[2] = {0};
24062 uint32_t v_rle_state = 0;
24063 uint32_t v_chunk_bits = 0;
24064 uint32_t v_chunk_count = 0;
24065
24066 const uint8_t* iop_a_src = NULL;
24067 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24068 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24069 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110024070 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024071 io0_a_src = a_src->data.ptr;
24072 io1_a_src = io0_a_src + a_src->meta.ri;
24073 iop_a_src = io1_a_src;
24074 io2_a_src = io0_a_src + a_src->meta.wi;
24075 }
24076
24077 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
24078 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
24079 if ((v_dst_bits_per_pixel & 7) != 0) {
24080 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
24081 goto exit;
24082 }
24083 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
24084 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
Nigel Tao123a5c62022-06-03 14:17:20 +100024085 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048));
Nigel Taoe360a532021-04-05 22:47:03 +100024086 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
24087 v_rle_state = self->private_impl.f_rle_state;
24088 label__outer__continue:;
24089 while (true) {
Nigel Taobf9dab32021-11-18 19:19:55 +110024090 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024091 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
24092 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
24093 }
24094 label__middle__continue:;
24095 while (true) {
24096 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
24097 if (v_i <= ((uint64_t)(v_row.len))) {
24098 v_dst = wuffs_base__slice_u8__subslice_i(v_row, v_i);
24099 } else {
24100 v_dst = wuffs_base__utility__empty_slice_u8();
24101 }
24102 while (true) {
24103 label__inner__continue:;
24104 while (true) {
24105 if (v_rle_state == 0) {
24106 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24107 goto label__goto_suspend__break;
24108 }
24109 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24110 iop_a_src += 1;
24111 if (v_code == 0) {
24112 v_rle_state = 2;
24113 goto label__inner__continue;
24114 }
24115 self->private_impl.f_rle_length = ((uint32_t)(v_code));
24116 v_rle_state = 1;
24117 goto label__inner__continue;
24118 } else if (v_rle_state == 1) {
24119 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24120 goto label__goto_suspend__break;
24121 }
24122 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24123 iop_a_src += 1;
24124 if (self->private_impl.f_bits_per_pixel == 8) {
24125 v_p0 = 0;
24126 while (v_p0 < self->private_impl.f_rle_length) {
24127 self->private_data.f_scratch[v_p0] = v_code;
24128 v_p0 += 1;
24129 }
24130 } else {
24131 v_indexes[0] = ((uint8_t)((v_code >> 4)));
24132 v_indexes[1] = (v_code & 15);
24133 v_p0 = 0;
24134 while (v_p0 < self->private_impl.f_rle_length) {
24135 self->private_data.f_scratch[(v_p0 + 0)] = v_indexes[0];
24136 self->private_data.f_scratch[(v_p0 + 1)] = v_indexes[1];
24137 v_p0 += 2;
24138 }
24139 }
Nigel Tao123a5c62022-06-03 14:17:20 +100024140 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_rle_length));
Nigel Taoe360a532021-04-05 22:47:03 +100024141 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, self->private_impl.f_rle_length);
24142 v_rle_state = 0;
24143 goto label__middle__continue;
24144 } else if (v_rle_state == 2) {
24145 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24146 goto label__goto_suspend__break;
24147 }
24148 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24149 iop_a_src += 1;
24150 if (v_code < 2) {
24151 if ((self->private_impl.f_dst_y >= self->private_impl.f_height) && (v_code == 0)) {
24152 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
24153 goto exit;
24154 }
24155 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_dst, v_dst_palette, 18446744073709551615u);
24156 self->private_impl.f_dst_x = 0;
24157 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
24158 if (v_code > 0) {
24159 goto label__outer__break;
24160 }
24161 v_rle_state = 0;
24162 goto label__outer__continue;
24163 } else if (v_code == 2) {
24164 v_rle_state = 4;
24165 goto label__inner__continue;
24166 }
24167 self->private_impl.f_rle_length = ((uint32_t)(v_code));
24168 self->private_impl.f_rle_padded = ((self->private_impl.f_bits_per_pixel == 8) && ((v_code & 1) != 0));
24169 v_rle_state = 3;
24170 goto label__inner__continue;
24171 } else if (v_rle_state == 3) {
24172 if (self->private_impl.f_bits_per_pixel == 8) {
24173 v_n = wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
24174 &self->private_impl.f_swizzler,
24175 self->private_impl.f_rle_length,
24176 v_dst,
24177 v_dst_palette,
24178 &iop_a_src,
24179 io2_a_src);
24180 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
24181 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, ((uint32_t)((v_n & 4294967295))));
24182 } else {
24183 v_chunk_count = ((self->private_impl.f_rle_length + 3) / 4);
24184 v_p0 = 0;
24185 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 2)) {
24186 v_chunk_bits = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
24187 iop_a_src += 2;
24188 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((15 & (v_chunk_bits >> 12))));
24189 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((15 & (v_chunk_bits >> 8))));
24190 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((15 & (v_chunk_bits >> 4))));
24191 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((15 & (v_chunk_bits >> 0))));
24192 v_p0 = ((v_p0 & 255) + 4);
24193 v_chunk_count -= 1;
24194 }
24195 v_p0 = wuffs_base__u32__min(v_p0, self->private_impl.f_rle_length);
Nigel Tao123a5c62022-06-03 14:17:20 +100024196 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0));
Nigel Taoe360a532021-04-05 22:47:03 +100024197 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, v_p0);
24198 wuffs_base__u32__sat_sub_indirect(&self->private_impl.f_rle_length, v_p0);
24199 }
24200 if (self->private_impl.f_rle_length > 0) {
24201 goto label__goto_suspend__break;
24202 }
24203 if (self->private_impl.f_rle_padded) {
24204 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24205 goto label__goto_suspend__break;
24206 }
24207 iop_a_src += 1;
24208 self->private_impl.f_rle_padded = false;
24209 }
24210 v_rle_state = 0;
24211 goto label__middle__continue;
24212 } else if (v_rle_state == 4) {
24213 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24214 goto label__goto_suspend__break;
24215 }
24216 self->private_impl.f_rle_delta_x = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24217 iop_a_src += 1;
24218 v_rle_state = 5;
24219 goto label__inner__continue;
24220 }
24221 if (((uint64_t)(io2_a_src - iop_a_src)) < 1) {
24222 goto label__goto_suspend__break;
24223 }
24224 v_code = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
24225 iop_a_src += 1;
24226 if (self->private_impl.f_rle_delta_x > 0) {
24227 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)));
24228 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)(self->private_impl.f_rle_delta_x)));
24229 self->private_impl.f_rle_delta_x = 0;
24230 if (self->private_impl.f_dst_x > self->private_impl.f_width) {
24231 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
24232 goto exit;
24233 }
24234 }
24235 if (v_code > 0) {
24236#if defined(__GNUC__)
24237#pragma GCC diagnostic push
24238#pragma GCC diagnostic ignored "-Wconversion"
24239#endif
24240 v_code -= 1;
24241#if defined(__GNUC__)
24242#pragma GCC diagnostic pop
24243#endif
24244 while (true) {
24245 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
24246 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
24247 status = wuffs_base__make_status(wuffs_bmp__error__bad_rle_compression);
24248 goto exit;
24249 }
Nigel Taobf9dab32021-11-18 19:19:55 +110024250 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024251 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
24252 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
24253 }
24254 if (v_code <= 0) {
24255 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)));
24256 goto label__0__break;
24257 }
24258 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u);
24259#if defined(__GNUC__)
24260#pragma GCC diagnostic push
24261#pragma GCC diagnostic ignored "-Wconversion"
24262#endif
24263 v_code -= 1;
24264#if defined(__GNUC__)
24265#pragma GCC diagnostic pop
24266#endif
24267 }
24268 label__0__break:;
24269 }
24270 v_rle_state = 0;
24271 goto label__middle__continue;
24272 }
24273 }
24274 label__goto_suspend__break:;
24275 self->private_impl.f_rle_state = v_rle_state;
24276 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
24277 goto ok;
24278 }
24279 }
24280 label__outer__break:;
24281 while (self->private_impl.f_dst_y < self->private_impl.f_height) {
Nigel Taobf9dab32021-11-18 19:19:55 +110024282 v_row = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024283 if (v_dst_bytes_per_row < ((uint64_t)(v_row.len))) {
24284 v_row = wuffs_base__slice_u8__subslice_j(v_row, v_dst_bytes_per_row);
24285 }
24286 wuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(&self->private_impl.f_swizzler, v_row, v_dst_palette, 18446744073709551615u);
24287 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
24288 }
24289 status = wuffs_base__make_status(NULL);
24290 goto ok;
24291
Nigel Taoe360a532021-04-05 22:47:03 +100024292 ok:
24293 goto exit;
24294 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110024295 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024296 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24297 }
24298
24299 return status;
24300}
24301
24302// -------- func bmp.decoder.swizzle_bitfields
24303
24304static wuffs_base__status
24305wuffs_bmp__decoder__swizzle_bitfields(
24306 wuffs_bmp__decoder* self,
24307 wuffs_base__pixel_buffer* a_dst,
24308 wuffs_base__io_buffer* a_src) {
24309 wuffs_base__status status = wuffs_base__make_status(NULL);
24310
24311 wuffs_base__pixel_format v_dst_pixfmt = {0};
24312 uint32_t v_dst_bits_per_pixel = 0;
24313 uint64_t v_dst_bytes_per_pixel = 0;
24314 uint64_t v_dst_bytes_per_row = 0;
24315 wuffs_base__slice_u8 v_dst_palette = {0};
24316 wuffs_base__table_u8 v_tab = {0};
24317 wuffs_base__slice_u8 v_dst = {0};
24318 uint64_t v_i = 0;
24319 uint64_t v_n = 0;
24320 uint32_t v_p0 = 0;
24321 uint32_t v_p1 = 0;
24322 uint32_t v_p1_temp = 0;
24323 uint32_t v_num_bits = 0;
24324 uint32_t v_c = 0;
24325 uint32_t v_c32 = 0;
24326 uint32_t v_channel = 0;
24327
24328 const uint8_t* iop_a_src = NULL;
24329 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24330 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24331 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110024332 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024333 io0_a_src = a_src->data.ptr;
24334 io1_a_src = io0_a_src + a_src->meta.ri;
24335 iop_a_src = io1_a_src;
24336 io2_a_src = io0_a_src + a_src->meta.wi;
24337 }
24338
24339 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
24340 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
24341 if ((v_dst_bits_per_pixel & 7) != 0) {
24342 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
24343 goto exit;
24344 }
24345 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
24346 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
Nigel Tao123a5c62022-06-03 14:17:20 +100024347 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048));
Nigel Taoe360a532021-04-05 22:47:03 +100024348 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
24349 label__outer__continue:;
24350 while (true) {
24351 while (self->private_impl.f_pending_pad > 0) {
24352 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
24353 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
24354 goto ok;
24355 }
24356 self->private_impl.f_pending_pad -= 1;
24357 iop_a_src += 1;
24358 }
24359 label__inner__continue:;
24360 while (true) {
24361 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
24362 self->private_impl.f_dst_x = 0;
24363 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
24364 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
24365 if (self->private_impl.f_height > 0) {
24366 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
24367 }
24368 goto label__outer__break;
24369 } else if (self->private_impl.f_pad_per_row != 0) {
24370 self->private_impl.f_pending_pad = self->private_impl.f_pad_per_row;
24371 goto label__outer__continue;
24372 }
24373 }
24374 v_p1_temp = ((uint32_t)(self->private_impl.f_width - self->private_impl.f_dst_x));
24375 v_p1 = wuffs_base__u32__min(v_p1_temp, 256);
24376 v_p0 = 0;
24377 while (v_p0 < v_p1) {
24378 if (self->private_impl.f_bits_per_pixel == 16) {
24379 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
24380 goto label__0__break;
24381 }
24382 v_c32 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
24383 iop_a_src += 2;
24384 } else {
24385 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
24386 goto label__0__break;
24387 }
24388 v_c32 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
24389 iop_a_src += 4;
24390 }
24391 v_channel = 0;
24392 while (v_channel < 4) {
24393 if (self->private_impl.f_channel_num_bits[v_channel] == 0) {
24394 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 0)] = 255;
24395 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 1)] = 255;
24396 } else {
24397 v_c = ((v_c32 & self->private_impl.f_channel_masks[v_channel]) >> self->private_impl.f_channel_shifts[v_channel]);
24398 v_num_bits = ((uint32_t)(self->private_impl.f_channel_num_bits[v_channel]));
24399 while (v_num_bits < 16) {
24400 v_c |= ((uint32_t)(v_c << v_num_bits));
24401 v_num_bits *= 2;
24402 }
24403 v_c >>= (v_num_bits - 16);
24404 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 0)] = ((uint8_t)((255 & (v_c >> 0))));
24405 self->private_data.f_scratch[((8 * v_p0) + (2 * v_channel) + 1)] = ((uint8_t)((255 & (v_c >> 8))));
24406 }
24407 v_channel += 1;
24408 }
24409 v_p0 += 1;
24410 }
24411 label__0__break:;
Nigel Taobf9dab32021-11-18 19:19:55 +110024412 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024413 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
24414 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
24415 }
24416 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
24417 if (v_i >= ((uint64_t)(v_dst.len))) {
24418 goto label__inner__continue;
24419 }
Nigel Tao123a5c62022-06-03 14:17:20 +100024420 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, wuffs_base__slice_u8__subslice_i(v_dst, v_i), v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, (8 * v_p0)));
Nigel Taoe360a532021-04-05 22:47:03 +100024421 if (v_n == 0) {
24422 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
24423 goto ok;
24424 }
24425 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
24426 }
24427 }
24428 label__outer__break:;
24429 status = wuffs_base__make_status(NULL);
24430 goto ok;
24431
Nigel Taoe360a532021-04-05 22:47:03 +100024432 ok:
24433 goto exit;
24434 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110024435 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024436 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24437 }
24438
24439 return status;
24440}
24441
24442// -------- func bmp.decoder.swizzle_low_bit_depth
24443
24444static wuffs_base__status
24445wuffs_bmp__decoder__swizzle_low_bit_depth(
24446 wuffs_bmp__decoder* self,
24447 wuffs_base__pixel_buffer* a_dst,
24448 wuffs_base__io_buffer* a_src) {
24449 wuffs_base__status status = wuffs_base__make_status(NULL);
24450
24451 wuffs_base__pixel_format v_dst_pixfmt = {0};
24452 uint32_t v_dst_bits_per_pixel = 0;
24453 uint64_t v_dst_bytes_per_pixel = 0;
24454 uint64_t v_dst_bytes_per_row = 0;
24455 wuffs_base__slice_u8 v_dst_palette = {0};
24456 wuffs_base__table_u8 v_tab = {0};
24457 wuffs_base__slice_u8 v_dst = {0};
24458 uint64_t v_i = 0;
24459 uint64_t v_n = 0;
24460 uint32_t v_p0 = 0;
24461 uint32_t v_chunk_bits = 0;
24462 uint32_t v_chunk_count = 0;
24463
24464 const uint8_t* iop_a_src = NULL;
24465 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24466 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24467 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110024468 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024469 io0_a_src = a_src->data.ptr;
24470 io1_a_src = io0_a_src + a_src->meta.ri;
24471 iop_a_src = io1_a_src;
24472 io2_a_src = io0_a_src + a_src->meta.wi;
24473 }
24474
24475 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
24476 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
24477 if ((v_dst_bits_per_pixel & 7) != 0) {
24478 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
24479 goto exit;
24480 }
24481 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
24482 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
Nigel Tao123a5c62022-06-03 14:17:20 +100024483 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8_ij(self->private_data.f_scratch, 1024, 2048));
Nigel Taoe360a532021-04-05 22:47:03 +100024484 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
24485 label__loop__continue:;
24486 while (true) {
24487 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
24488 self->private_impl.f_dst_x = 0;
24489 self->private_impl.f_dst_y += self->private_impl.f_dst_y_inc;
24490 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
24491 goto label__loop__break;
24492 }
24493 }
Nigel Taobf9dab32021-11-18 19:19:55 +110024494 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100024495 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
24496 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
24497 }
24498 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
24499 if (v_i >= ((uint64_t)(v_dst.len))) {
24500 goto label__loop__continue;
24501 }
24502 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i);
24503 v_p0 = 0;
24504 if (self->private_impl.f_bits_per_pixel == 1) {
24505 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 31) / 32);
24506 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 16);
24507 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
24508 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
24509 iop_a_src += 4;
24510 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((1 & (v_chunk_bits >> 31))));
24511 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((1 & (v_chunk_bits >> 30))));
24512 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((1 & (v_chunk_bits >> 29))));
24513 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((1 & (v_chunk_bits >> 28))));
24514 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((1 & (v_chunk_bits >> 27))));
24515 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((1 & (v_chunk_bits >> 26))));
24516 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((1 & (v_chunk_bits >> 25))));
24517 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((1 & (v_chunk_bits >> 24))));
24518 self->private_data.f_scratch[(v_p0 + 8)] = ((uint8_t)((1 & (v_chunk_bits >> 23))));
24519 self->private_data.f_scratch[(v_p0 + 9)] = ((uint8_t)((1 & (v_chunk_bits >> 22))));
24520 self->private_data.f_scratch[(v_p0 + 10)] = ((uint8_t)((1 & (v_chunk_bits >> 21))));
24521 self->private_data.f_scratch[(v_p0 + 11)] = ((uint8_t)((1 & (v_chunk_bits >> 20))));
24522 self->private_data.f_scratch[(v_p0 + 12)] = ((uint8_t)((1 & (v_chunk_bits >> 19))));
24523 self->private_data.f_scratch[(v_p0 + 13)] = ((uint8_t)((1 & (v_chunk_bits >> 18))));
24524 self->private_data.f_scratch[(v_p0 + 14)] = ((uint8_t)((1 & (v_chunk_bits >> 17))));
24525 self->private_data.f_scratch[(v_p0 + 15)] = ((uint8_t)((1 & (v_chunk_bits >> 16))));
24526 self->private_data.f_scratch[(v_p0 + 16)] = ((uint8_t)((1 & (v_chunk_bits >> 15))));
24527 self->private_data.f_scratch[(v_p0 + 17)] = ((uint8_t)((1 & (v_chunk_bits >> 14))));
24528 self->private_data.f_scratch[(v_p0 + 18)] = ((uint8_t)((1 & (v_chunk_bits >> 13))));
24529 self->private_data.f_scratch[(v_p0 + 19)] = ((uint8_t)((1 & (v_chunk_bits >> 12))));
24530 self->private_data.f_scratch[(v_p0 + 20)] = ((uint8_t)((1 & (v_chunk_bits >> 11))));
24531 self->private_data.f_scratch[(v_p0 + 21)] = ((uint8_t)((1 & (v_chunk_bits >> 10))));
24532 self->private_data.f_scratch[(v_p0 + 22)] = ((uint8_t)((1 & (v_chunk_bits >> 9))));
24533 self->private_data.f_scratch[(v_p0 + 23)] = ((uint8_t)((1 & (v_chunk_bits >> 8))));
24534 self->private_data.f_scratch[(v_p0 + 24)] = ((uint8_t)((1 & (v_chunk_bits >> 7))));
24535 self->private_data.f_scratch[(v_p0 + 25)] = ((uint8_t)((1 & (v_chunk_bits >> 6))));
24536 self->private_data.f_scratch[(v_p0 + 26)] = ((uint8_t)((1 & (v_chunk_bits >> 5))));
24537 self->private_data.f_scratch[(v_p0 + 27)] = ((uint8_t)((1 & (v_chunk_bits >> 4))));
24538 self->private_data.f_scratch[(v_p0 + 28)] = ((uint8_t)((1 & (v_chunk_bits >> 3))));
24539 self->private_data.f_scratch[(v_p0 + 29)] = ((uint8_t)((1 & (v_chunk_bits >> 2))));
24540 self->private_data.f_scratch[(v_p0 + 30)] = ((uint8_t)((1 & (v_chunk_bits >> 1))));
24541 self->private_data.f_scratch[(v_p0 + 31)] = ((uint8_t)((1 & (v_chunk_bits >> 0))));
24542 v_p0 = ((v_p0 & 511) + 32);
24543 v_chunk_count -= 1;
24544 }
24545 } else if (self->private_impl.f_bits_per_pixel == 2) {
24546 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 15) / 16);
24547 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 32);
24548 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
24549 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
24550 iop_a_src += 4;
24551 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((3 & (v_chunk_bits >> 30))));
24552 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((3 & (v_chunk_bits >> 28))));
24553 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((3 & (v_chunk_bits >> 26))));
24554 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((3 & (v_chunk_bits >> 24))));
24555 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((3 & (v_chunk_bits >> 22))));
24556 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((3 & (v_chunk_bits >> 20))));
24557 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((3 & (v_chunk_bits >> 18))));
24558 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((3 & (v_chunk_bits >> 16))));
24559 self->private_data.f_scratch[(v_p0 + 8)] = ((uint8_t)((3 & (v_chunk_bits >> 14))));
24560 self->private_data.f_scratch[(v_p0 + 9)] = ((uint8_t)((3 & (v_chunk_bits >> 12))));
24561 self->private_data.f_scratch[(v_p0 + 10)] = ((uint8_t)((3 & (v_chunk_bits >> 10))));
24562 self->private_data.f_scratch[(v_p0 + 11)] = ((uint8_t)((3 & (v_chunk_bits >> 8))));
24563 self->private_data.f_scratch[(v_p0 + 12)] = ((uint8_t)((3 & (v_chunk_bits >> 6))));
24564 self->private_data.f_scratch[(v_p0 + 13)] = ((uint8_t)((3 & (v_chunk_bits >> 4))));
24565 self->private_data.f_scratch[(v_p0 + 14)] = ((uint8_t)((3 & (v_chunk_bits >> 2))));
24566 self->private_data.f_scratch[(v_p0 + 15)] = ((uint8_t)((3 & (v_chunk_bits >> 0))));
24567 v_p0 = ((v_p0 & 511) + 16);
24568 v_chunk_count -= 1;
24569 }
24570 } else if (self->private_impl.f_bits_per_pixel == 4) {
24571 v_chunk_count = ((wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x) + 7) / 8);
24572 v_chunk_count = wuffs_base__u32__min(v_chunk_count, 64);
24573 while ((v_chunk_count > 0) && (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
24574 v_chunk_bits = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
24575 iop_a_src += 4;
24576 self->private_data.f_scratch[(v_p0 + 0)] = ((uint8_t)((15 & (v_chunk_bits >> 28))));
24577 self->private_data.f_scratch[(v_p0 + 1)] = ((uint8_t)((15 & (v_chunk_bits >> 24))));
24578 self->private_data.f_scratch[(v_p0 + 2)] = ((uint8_t)((15 & (v_chunk_bits >> 20))));
24579 self->private_data.f_scratch[(v_p0 + 3)] = ((uint8_t)((15 & (v_chunk_bits >> 16))));
24580 self->private_data.f_scratch[(v_p0 + 4)] = ((uint8_t)((15 & (v_chunk_bits >> 12))));
24581 self->private_data.f_scratch[(v_p0 + 5)] = ((uint8_t)((15 & (v_chunk_bits >> 8))));
24582 self->private_data.f_scratch[(v_p0 + 6)] = ((uint8_t)((15 & (v_chunk_bits >> 4))));
24583 self->private_data.f_scratch[(v_p0 + 7)] = ((uint8_t)((15 & (v_chunk_bits >> 0))));
24584 v_p0 = ((v_p0 & 511) + 8);
24585 v_chunk_count -= 1;
24586 }
24587 }
24588 v_p0 = wuffs_base__u32__min(v_p0, wuffs_base__u32__sat_sub(self->private_impl.f_width, self->private_impl.f_dst_x));
Nigel Tao123a5c62022-06-03 14:17:20 +100024589 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, v_p0));
Nigel Taoe360a532021-04-05 22:47:03 +100024590 if (v_n == 0) {
24591 status = wuffs_base__make_status(wuffs_bmp__note__internal_note_short_read);
24592 goto ok;
24593 }
24594 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
24595 }
24596 label__loop__break:;
24597 status = wuffs_base__make_status(NULL);
24598 goto ok;
24599
Nigel Taoe360a532021-04-05 22:47:03 +100024600 ok:
24601 goto exit;
24602 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110024603 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024604 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24605 }
24606
24607 return status;
24608}
24609
24610// -------- func bmp.decoder.frame_dirty_rect
24611
24612WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
24613wuffs_bmp__decoder__frame_dirty_rect(
24614 const wuffs_bmp__decoder* self) {
24615 if (!self) {
24616 return wuffs_base__utility__empty_rect_ie_u32();
24617 }
24618 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24619 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24620 return wuffs_base__utility__empty_rect_ie_u32();
24621 }
24622
24623 return wuffs_base__utility__make_rect_ie_u32(
24624 0,
24625 0,
24626 self->private_impl.f_width,
24627 self->private_impl.f_height);
24628}
24629
24630// -------- func bmp.decoder.num_animation_loops
24631
24632WUFFS_BASE__MAYBE_STATIC uint32_t
24633wuffs_bmp__decoder__num_animation_loops(
24634 const wuffs_bmp__decoder* self) {
24635 if (!self) {
24636 return 0;
24637 }
24638 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24639 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24640 return 0;
24641 }
24642
24643 return 0;
24644}
24645
24646// -------- func bmp.decoder.num_decoded_frame_configs
24647
24648WUFFS_BASE__MAYBE_STATIC uint64_t
24649wuffs_bmp__decoder__num_decoded_frame_configs(
24650 const wuffs_bmp__decoder* self) {
24651 if (!self) {
24652 return 0;
24653 }
24654 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24655 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24656 return 0;
24657 }
24658
Nigel Tao123a5c62022-06-03 14:17:20 +100024659 if (self->private_impl.f_call_sequence > 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100024660 return 1;
24661 }
24662 return 0;
24663}
24664
24665// -------- func bmp.decoder.num_decoded_frames
24666
24667WUFFS_BASE__MAYBE_STATIC uint64_t
24668wuffs_bmp__decoder__num_decoded_frames(
24669 const wuffs_bmp__decoder* self) {
24670 if (!self) {
24671 return 0;
24672 }
24673 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24674 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24675 return 0;
24676 }
24677
Nigel Tao123a5c62022-06-03 14:17:20 +100024678 if (self->private_impl.f_call_sequence > 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100024679 return 1;
24680 }
24681 return 0;
24682}
24683
24684// -------- func bmp.decoder.restart_frame
24685
24686WUFFS_BASE__MAYBE_STATIC wuffs_base__status
24687wuffs_bmp__decoder__restart_frame(
24688 wuffs_bmp__decoder* self,
24689 uint64_t a_index,
24690 uint64_t a_io_position) {
24691 if (!self) {
24692 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
24693 }
24694 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
24695 return wuffs_base__make_status(
24696 (self->private_impl.magic == WUFFS_BASE__DISABLED)
24697 ? wuffs_base__error__disabled_by_previous_error
24698 : wuffs_base__error__initialize_not_called);
24699 }
24700
Nigel Tao123a5c62022-06-03 14:17:20 +100024701 if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100024702 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
24703 }
24704 if (a_index != 0) {
24705 return wuffs_base__make_status(wuffs_base__error__bad_argument);
24706 }
Nigel Tao123a5c62022-06-03 14:17:20 +100024707 self->private_impl.f_call_sequence = 40;
Nigel Taoe360a532021-04-05 22:47:03 +100024708 self->private_impl.f_frame_config_io_position = a_io_position;
24709 return wuffs_base__make_status(NULL);
24710}
24711
24712// -------- func bmp.decoder.set_report_metadata
24713
24714WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
24715wuffs_bmp__decoder__set_report_metadata(
24716 wuffs_bmp__decoder* self,
24717 uint32_t a_fourcc,
24718 bool a_report) {
24719 return wuffs_base__make_empty_struct();
24720}
24721
24722// -------- func bmp.decoder.tell_me_more
24723
24724WUFFS_BASE__MAYBE_STATIC wuffs_base__status
24725wuffs_bmp__decoder__tell_me_more(
24726 wuffs_bmp__decoder* self,
24727 wuffs_base__io_buffer* a_dst,
24728 wuffs_base__more_information* a_minfo,
24729 wuffs_base__io_buffer* a_src) {
24730 if (!self) {
24731 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
24732 }
24733 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
24734 return wuffs_base__make_status(
24735 (self->private_impl.magic == WUFFS_BASE__DISABLED)
24736 ? wuffs_base__error__disabled_by_previous_error
24737 : wuffs_base__error__initialize_not_called);
24738 }
24739 if (!a_dst || !a_src) {
24740 self->private_impl.magic = WUFFS_BASE__DISABLED;
24741 return wuffs_base__make_status(wuffs_base__error__bad_argument);
24742 }
24743 if ((self->private_impl.active_coroutine != 0) &&
24744 (self->private_impl.active_coroutine != 4)) {
24745 self->private_impl.magic = WUFFS_BASE__DISABLED;
24746 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
24747 }
24748 self->private_impl.active_coroutine = 0;
24749 wuffs_base__status status = wuffs_base__make_status(NULL);
24750
24751 if (self->private_impl.f_io_redirect_fourcc <= 1) {
24752 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
24753 goto exit;
24754 }
24755 if (a_minfo != NULL) {
24756 wuffs_base__more_information__set(a_minfo,
24757 1,
24758 self->private_impl.f_io_redirect_fourcc,
24759 0,
24760 self->private_impl.f_io_redirect_pos,
24761 18446744073709551615u);
24762 }
24763 self->private_impl.f_io_redirect_fourcc = 1;
24764
24765 goto ok;
24766 ok:
24767 goto exit;
24768 exit:
24769 if (wuffs_base__status__is_error(&status)) {
24770 self->private_impl.magic = WUFFS_BASE__DISABLED;
24771 }
24772 return status;
24773}
24774
24775// -------- func bmp.decoder.workbuf_len
24776
24777WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
24778wuffs_bmp__decoder__workbuf_len(
24779 const wuffs_bmp__decoder* self) {
24780 if (!self) {
24781 return wuffs_base__utility__empty_range_ii_u64();
24782 }
24783 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
24784 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
24785 return wuffs_base__utility__empty_range_ii_u64();
24786 }
24787
24788 return wuffs_base__utility__make_range_ii_u64(0, 0);
24789}
24790
24791// -------- func bmp.decoder.read_palette
24792
24793static wuffs_base__status
24794wuffs_bmp__decoder__read_palette(
24795 wuffs_bmp__decoder* self,
24796 wuffs_base__io_buffer* a_src) {
24797 wuffs_base__status status = wuffs_base__make_status(NULL);
24798
24799 uint32_t v_i = 0;
24800 uint32_t v_argb = 0;
24801
24802 const uint8_t* iop_a_src = NULL;
24803 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24804 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
24805 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110024806 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024807 io0_a_src = a_src->data.ptr;
24808 io1_a_src = io0_a_src + a_src->meta.ri;
24809 iop_a_src = io1_a_src;
24810 io2_a_src = io0_a_src + a_src->meta.wi;
24811 }
24812
24813 uint32_t coro_susp_point = self->private_impl.p_read_palette[0];
24814 if (coro_susp_point) {
24815 v_i = self->private_data.s_read_palette[0].v_i;
24816 }
24817 switch (coro_susp_point) {
24818 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
24819
24820 if (self->private_impl.f_bitmap_info_len == 12) {
24821 while ((v_i < 256) && (self->private_impl.f_padding >= 3)) {
24822 self->private_impl.f_padding -= 3;
24823 {
24824 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
24825 uint32_t t_0;
24826 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
24827 t_0 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
24828 iop_a_src += 3;
24829 } else {
24830 self->private_data.s_read_palette[0].scratch = 0;
24831 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
24832 while (true) {
24833 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
24834 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24835 goto suspend;
24836 }
24837 uint64_t* scratch = &self->private_data.s_read_palette[0].scratch;
24838 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
24839 *scratch <<= 8;
24840 *scratch >>= 8;
24841 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
24842 if (num_bits_0 == 16) {
24843 t_0 = ((uint32_t)(*scratch));
24844 break;
24845 }
24846 num_bits_0 += 8;
24847 *scratch |= ((uint64_t)(num_bits_0)) << 56;
24848 }
24849 }
24850 v_argb = t_0;
24851 }
24852 v_argb |= 4278190080;
24853 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
24854 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
24855 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
24856 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
24857 v_i += 1;
24858 }
24859 } else {
24860 while ((v_i < 256) && (self->private_impl.f_padding >= 4)) {
24861 self->private_impl.f_padding -= 4;
24862 {
24863 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
24864 uint32_t t_1;
24865 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
24866 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
24867 iop_a_src += 4;
24868 } else {
24869 self->private_data.s_read_palette[0].scratch = 0;
24870 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
24871 while (true) {
24872 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
24873 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
24874 goto suspend;
24875 }
24876 uint64_t* scratch = &self->private_data.s_read_palette[0].scratch;
24877 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
24878 *scratch <<= 8;
24879 *scratch >>= 8;
24880 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
24881 if (num_bits_1 == 24) {
24882 t_1 = ((uint32_t)(*scratch));
24883 break;
24884 }
24885 num_bits_1 += 8;
24886 *scratch |= ((uint64_t)(num_bits_1)) << 56;
24887 }
24888 }
24889 v_argb = t_1;
24890 }
24891 v_argb |= 4278190080;
24892 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
24893 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
24894 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
24895 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
24896 v_i += 1;
24897 }
24898 }
24899 while (v_i < 256) {
24900 self->private_data.f_src_palette[((4 * v_i) + 0)] = 0;
24901 self->private_data.f_src_palette[((4 * v_i) + 1)] = 0;
24902 self->private_data.f_src_palette[((4 * v_i) + 2)] = 0;
24903 self->private_data.f_src_palette[((4 * v_i) + 3)] = 255;
24904 v_i += 1;
24905 }
24906
24907 goto ok;
24908 ok:
24909 self->private_impl.p_read_palette[0] = 0;
24910 goto exit;
24911 }
24912
24913 goto suspend;
24914 suspend:
24915 self->private_impl.p_read_palette[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
24916 self->private_data.s_read_palette[0].v_i = v_i;
24917
24918 goto exit;
24919 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110024920 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100024921 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
24922 }
24923
24924 return status;
24925}
24926
24927// -------- func bmp.decoder.process_masks
24928
24929static wuffs_base__status
24930wuffs_bmp__decoder__process_masks(
24931 wuffs_bmp__decoder* self) {
24932 wuffs_base__status status = wuffs_base__make_status(NULL);
24933
24934 uint32_t v_i = 0;
24935 uint32_t v_mask = 0;
24936 uint32_t v_n = 0;
24937
24938 while (v_i < 4) {
24939 v_mask = self->private_impl.f_channel_masks[v_i];
24940 if (v_mask != 0) {
24941 v_n = 0;
24942 while ((v_mask & 1) == 0) {
24943 v_n += 1;
24944 v_mask >>= 1;
24945 }
24946 self->private_impl.f_channel_shifts[v_i] = ((uint8_t)((v_n & 31)));
24947 v_n = 0;
24948 while ((v_mask & 1) == 1) {
24949 v_n += 1;
24950 v_mask >>= 1;
24951 }
24952 if ((v_mask != 0) || (v_n > 32)) {
24953 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
24954 goto exit;
24955 }
24956 self->private_impl.f_channel_num_bits[v_i] = ((uint8_t)(v_n));
24957 } else if (v_i != 3) {
24958 status = wuffs_base__make_status(wuffs_bmp__error__bad_header);
24959 goto exit;
24960 }
24961 v_i += 1;
24962 }
24963
24964 goto ok;
24965 ok:
24966 goto exit;
24967 exit:
24968 return status;
24969}
24970
24971#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
24972
Nigel Tao123a5c62022-06-03 14:17:20 +100024973#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2)
24974
24975// ---------------- Status Codes Implementations
24976
24977const char wuffs_bzip2__error__bad_huffman_code_over_subscribed[] = "#bzip2: bad Huffman code (over-subscribed)";
24978const char wuffs_bzip2__error__bad_huffman_code_under_subscribed[] = "#bzip2: bad Huffman code (under-subscribed)";
24979const char wuffs_bzip2__error__bad_block_header[] = "#bzip2: bad block header";
24980const char wuffs_bzip2__error__bad_block_length[] = "#bzip2: bad block length";
24981const char wuffs_bzip2__error__bad_checksum[] = "#bzip2: bad checksum";
24982const char wuffs_bzip2__error__bad_header[] = "#bzip2: bad header";
Nigel Tao123a5c62022-06-03 14:17:20 +100024983const char wuffs_bzip2__error__bad_number_of_sections[] = "#bzip2: bad number of sections";
Nigel Tao123a5c62022-06-03 14:17:20 +100024984const char wuffs_bzip2__error__unsupported_block_randomization[] = "#bzip2: unsupported block randomization";
24985const char wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state[] = "#bzip2: internal error: inconsistent Huffman decoder state";
24986
24987// ---------------- Private Consts
24988
24989static const uint8_t
24990WUFFS_BZIP2__CLAMP_TO_5[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
24991 0, 1, 2, 3, 4, 5, 5, 5,
24992};
24993
24994static const uint32_t
24995WUFFS_BZIP2__REV_CRC32_TABLE[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
24996 0, 79764919, 159529838, 222504665, 319059676, 398814059, 445009330, 507990021,
24997 638119352, 583659535, 797628118, 726387553, 890018660, 835552979, 1015980042, 944750013,
24998 1276238704, 1221641927, 1167319070, 1095957929, 1595256236, 1540665371, 1452775106, 1381403509,
24999 1780037320, 1859660671, 1671105958, 1733955601, 2031960084, 2111593891, 1889500026, 1952343757,
25000 2552477408, 2632100695, 2443283854, 2506133561, 2334638140, 2414271883, 2191915858, 2254759653,
25001 3190512472, 3135915759, 3081330742, 3009969537, 2905550212, 2850959411, 2762807018, 2691435357,
25002 3560074640, 3505614887, 3719321342, 3648080713, 3342211916, 3287746299, 3467911202, 3396681109,
25003 4063920168, 4143685023, 4223187782, 4286162673, 3779000052, 3858754371, 3904687514, 3967668269,
25004 881225847, 809987520, 1023691545, 969234094, 662832811, 591600412, 771767749, 717299826,
25005 311336399, 374308984, 453813921, 533576470, 25881363, 88864420, 134795389, 214552010,
25006 2023205639, 2086057648, 1897238633, 1976864222, 1804852699, 1867694188, 1645340341, 1724971778,
25007 1587496639, 1516133128, 1461550545, 1406951526, 1302016099, 1230646740, 1142491917, 1087903418,
25008 2896545431, 2825181984, 2770861561, 2716262478, 3215044683, 3143675388, 3055782693, 3001194130,
25009 2326604591, 2389456536, 2200899649, 2280525302, 2578013683, 2640855108, 2418763421, 2498394922,
25010 3769900519, 3832873040, 3912640137, 3992402750, 4088425275, 4151408268, 4197601365, 4277358050,
25011 3334271071, 3263032808, 3476998961, 3422541446, 3585640067, 3514407732, 3694837229, 3640369242,
25012 1762451694, 1842216281, 1619975040, 1682949687, 2047383090, 2127137669, 1938468188, 2001449195,
25013 1325665622, 1271206113, 1183200824, 1111960463, 1543535498, 1489069629, 1434599652, 1363369299,
25014 622672798, 568075817, 748617968, 677256519, 907627842, 853037301, 1067152940, 995781531,
25015 51762726, 131386257, 177728840, 240578815, 269590778, 349224269, 429104020, 491947555,
25016 4046411278, 4126034873, 4172115296, 4234965207, 3794477266, 3874110821, 3953728444, 4016571915,
25017 3609705398, 3555108353, 3735388376, 3664026991, 3290680682, 3236090077, 3449943556, 3378572211,
25018 3174993278, 3120533705, 3032266256, 2961025959, 2923101090, 2868635157, 2813903052, 2742672763,
25019 2604032198, 2683796849, 2461293480, 2524268063, 2284983834, 2364738477, 2175806836, 2238787779,
25020 1569362073, 1498123566, 1409854455, 1355396672, 1317987909, 1246755826, 1192025387, 1137557660,
25021 2072149281, 2135122070, 1912620623, 1992383480, 1753615357, 1816598090, 1627664531, 1707420964,
25022 295390185, 358241886, 404320391, 483945776, 43990325, 106832002, 186451547, 266083308,
25023 932423249, 861060070, 1041341759, 986742920, 613929101, 542559546, 756411363, 701822548,
25024 3316196985, 3244833742, 3425377559, 3370778784, 3601682597, 3530312978, 3744426955, 3689838204,
25025 3819031489, 3881883254, 3928223919, 4007849240, 4037393693, 4100235434, 4180117107, 4259748804,
25026 2310601993, 2373574846, 2151335527, 2231098320, 2596047829, 2659030626, 2470359227, 2550115596,
25027 2947551409, 2876312838, 2788305887, 2733848168, 3165939309, 3094707162, 3040238851, 2985771188,
25028};
25029
25030// ---------------- Private Initializer Prototypes
25031
25032// ---------------- Private Function Prototypes
25033
25034static wuffs_base__status
25035wuffs_bzip2__decoder__prepare_block(
25036 wuffs_bzip2__decoder* self,
25037 wuffs_base__io_buffer* a_src);
25038
25039static wuffs_base__status
25040wuffs_bzip2__decoder__read_code_lengths(
25041 wuffs_bzip2__decoder* self,
25042 wuffs_base__io_buffer* a_src);
25043
25044static wuffs_base__status
25045wuffs_bzip2__decoder__build_huffman_tree(
25046 wuffs_bzip2__decoder* self,
25047 uint32_t a_which);
25048
25049static wuffs_base__empty_struct
25050wuffs_bzip2__decoder__build_huffman_table(
25051 wuffs_bzip2__decoder* self,
25052 uint32_t a_which);
25053
25054static wuffs_base__empty_struct
25055wuffs_bzip2__decoder__invert_bwt(
25056 wuffs_bzip2__decoder* self);
25057
25058static wuffs_base__empty_struct
25059wuffs_bzip2__decoder__flush_fast(
25060 wuffs_bzip2__decoder* self,
25061 wuffs_base__io_buffer* a_dst);
25062
25063static wuffs_base__status
25064wuffs_bzip2__decoder__flush_slow(
25065 wuffs_bzip2__decoder* self,
25066 wuffs_base__io_buffer* a_dst);
25067
25068static wuffs_base__status
25069wuffs_bzip2__decoder__decode_huffman_fast(
25070 wuffs_bzip2__decoder* self,
25071 wuffs_base__io_buffer* a_src);
25072
25073static wuffs_base__status
25074wuffs_bzip2__decoder__decode_huffman_slow(
25075 wuffs_bzip2__decoder* self,
25076 wuffs_base__io_buffer* a_src);
25077
25078// ---------------- VTables
25079
25080const wuffs_base__io_transformer__func_ptrs
25081wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer = {
25082 (wuffs_base__empty_struct(*)(void*,
25083 uint32_t,
25084 bool))(&wuffs_bzip2__decoder__set_quirk_enabled),
25085 (wuffs_base__status(*)(void*,
25086 wuffs_base__io_buffer*,
25087 wuffs_base__io_buffer*,
25088 wuffs_base__slice_u8))(&wuffs_bzip2__decoder__transform_io),
25089 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_bzip2__decoder__workbuf_len),
25090};
25091
25092// ---------------- Initializer Implementations
25093
25094wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
25095wuffs_bzip2__decoder__initialize(
25096 wuffs_bzip2__decoder* self,
25097 size_t sizeof_star_self,
25098 uint64_t wuffs_version,
25099 uint32_t options){
25100 if (!self) {
25101 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
25102 }
25103 if (sizeof(*self) != sizeof_star_self) {
25104 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
25105 }
25106 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
25107 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
25108 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
25109 }
25110
25111 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
25112 // The whole point of this if-check is to detect an uninitialized *self.
25113 // We disable the warning on GCC. Clang-5.0 does not have this warning.
25114#if !defined(__clang__) && defined(__GNUC__)
25115#pragma GCC diagnostic push
25116#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
25117#endif
25118 if (self->private_impl.magic != 0) {
25119 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
25120 }
25121#if !defined(__clang__) && defined(__GNUC__)
25122#pragma GCC diagnostic pop
25123#endif
25124 } else {
25125 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
25126 memset(self, 0, sizeof(*self));
25127 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
25128 } else {
25129 memset(&(self->private_impl), 0, sizeof(self->private_impl));
25130 }
25131 }
25132
25133 self->private_impl.magic = WUFFS_BASE__MAGIC;
25134 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
25135 wuffs_base__io_transformer__vtable_name;
25136 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
25137 (const void*)(&wuffs_bzip2__decoder__func_ptrs_for__wuffs_base__io_transformer);
25138 return wuffs_base__make_status(NULL);
25139}
25140
25141wuffs_bzip2__decoder*
25142wuffs_bzip2__decoder__alloc() {
25143 wuffs_bzip2__decoder* x =
25144 (wuffs_bzip2__decoder*)(calloc(sizeof(wuffs_bzip2__decoder), 1));
25145 if (!x) {
25146 return NULL;
25147 }
25148 if (wuffs_bzip2__decoder__initialize(
25149 x, sizeof(wuffs_bzip2__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
25150 free(x);
25151 return NULL;
25152 }
25153 return x;
25154}
25155
25156size_t
25157sizeof__wuffs_bzip2__decoder() {
25158 return sizeof(wuffs_bzip2__decoder);
25159}
25160
25161// ---------------- Function Implementations
25162
25163// -------- func bzip2.decoder.set_quirk_enabled
25164
25165WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
25166wuffs_bzip2__decoder__set_quirk_enabled(
25167 wuffs_bzip2__decoder* self,
25168 uint32_t a_quirk,
25169 bool a_enabled) {
25170 if (!self) {
25171 return wuffs_base__make_empty_struct();
25172 }
25173 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
25174 return wuffs_base__make_empty_struct();
25175 }
25176
25177 if (a_quirk == 1) {
25178 self->private_impl.f_ignore_checksum = a_enabled;
25179 }
25180 return wuffs_base__make_empty_struct();
25181}
25182
25183// -------- func bzip2.decoder.workbuf_len
25184
25185WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
25186wuffs_bzip2__decoder__workbuf_len(
25187 const wuffs_bzip2__decoder* self) {
25188 if (!self) {
25189 return wuffs_base__utility__empty_range_ii_u64();
25190 }
25191 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
25192 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
25193 return wuffs_base__utility__empty_range_ii_u64();
25194 }
25195
25196 return wuffs_base__utility__make_range_ii_u64(0, 0);
25197}
25198
25199// -------- func bzip2.decoder.transform_io
25200
25201WUFFS_BASE__MAYBE_STATIC wuffs_base__status
25202wuffs_bzip2__decoder__transform_io(
25203 wuffs_bzip2__decoder* self,
25204 wuffs_base__io_buffer* a_dst,
25205 wuffs_base__io_buffer* a_src,
25206 wuffs_base__slice_u8 a_workbuf) {
25207 if (!self) {
25208 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
25209 }
25210 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
25211 return wuffs_base__make_status(
25212 (self->private_impl.magic == WUFFS_BASE__DISABLED)
25213 ? wuffs_base__error__disabled_by_previous_error
25214 : wuffs_base__error__initialize_not_called);
25215 }
25216 if (!a_dst || !a_src) {
25217 self->private_impl.magic = WUFFS_BASE__DISABLED;
25218 return wuffs_base__make_status(wuffs_base__error__bad_argument);
25219 }
25220 if ((self->private_impl.active_coroutine != 0) &&
25221 (self->private_impl.active_coroutine != 1)) {
25222 self->private_impl.magic = WUFFS_BASE__DISABLED;
25223 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
25224 }
25225 self->private_impl.active_coroutine = 0;
25226 wuffs_base__status status = wuffs_base__make_status(NULL);
25227
25228 uint8_t v_c = 0;
25229 uint32_t v_i = 0;
25230 uint64_t v_tag = 0;
25231 wuffs_base__status v_status = wuffs_base__make_status(NULL);
25232 uint32_t v_final_checksum_want = 0;
25233
25234 const uint8_t* iop_a_src = NULL;
25235 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25236 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25237 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110025238 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025239 io0_a_src = a_src->data.ptr;
25240 io1_a_src = io0_a_src + a_src->meta.ri;
25241 iop_a_src = io1_a_src;
25242 io2_a_src = io0_a_src + a_src->meta.wi;
25243 }
25244
25245 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
25246 if (coro_susp_point) {
25247 v_i = self->private_data.s_transform_io[0].v_i;
25248 v_tag = self->private_data.s_transform_io[0].v_tag;
25249 v_final_checksum_want = self->private_data.s_transform_io[0].v_final_checksum_want;
25250 }
25251 switch (coro_susp_point) {
25252 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
25253
25254 {
25255 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
25256 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25257 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25258 goto suspend;
25259 }
25260 uint8_t t_0 = *iop_a_src++;
25261 v_c = t_0;
25262 }
25263 if (v_c != 66) {
25264 status = wuffs_base__make_status(wuffs_bzip2__error__bad_header);
25265 goto exit;
25266 }
25267 {
25268 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
25269 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25270 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25271 goto suspend;
25272 }
25273 uint8_t t_1 = *iop_a_src++;
25274 v_c = t_1;
25275 }
25276 if (v_c != 90) {
25277 status = wuffs_base__make_status(wuffs_bzip2__error__bad_header);
25278 goto exit;
25279 }
25280 {
25281 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
25282 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25283 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25284 goto suspend;
25285 }
25286 uint8_t t_2 = *iop_a_src++;
25287 v_c = t_2;
25288 }
25289 if (v_c != 104) {
25290 status = wuffs_base__make_status(wuffs_bzip2__error__bad_header);
25291 goto exit;
25292 }
25293 {
25294 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
25295 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25296 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25297 goto suspend;
25298 }
25299 uint8_t t_3 = *iop_a_src++;
25300 v_c = t_3;
25301 }
25302 if ((v_c < 49) || (57 < v_c)) {
25303 status = wuffs_base__make_status(wuffs_bzip2__error__bad_header);
25304 goto exit;
25305 }
25306 self->private_impl.f_max_incl_block_size = (((uint32_t)((v_c - 48))) * 100000);
25307 while (true) {
25308 v_tag = 0;
25309 v_i = 0;
25310 while (v_i < 48) {
25311 if (self->private_impl.f_n_bits <= 0) {
25312 {
25313 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
25314 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25315 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25316 goto suspend;
25317 }
25318 uint8_t t_4 = *iop_a_src++;
25319 v_c = t_4;
25320 }
25321 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25322 self->private_impl.f_n_bits = 8;
25323 }
25324 v_tag <<= 1;
25325 v_tag |= ((uint64_t)((self->private_impl.f_bits >> 31)));
25326 self->private_impl.f_bits <<= 1;
25327 self->private_impl.f_n_bits -= 1;
25328 v_i += 1;
25329 }
25330 if (v_tag == 25779555029136) {
25331 goto label__0__break;
25332 } else if (v_tag != 54156738319193) {
25333 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25334 goto exit;
25335 }
25336 if (a_src) {
25337 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25338 }
25339 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
25340 status = wuffs_bzip2__decoder__prepare_block(self, a_src);
25341 if (a_src) {
25342 iop_a_src = a_src->data.ptr + a_src->meta.ri;
25343 }
25344 if (status.repr) {
25345 goto suspend;
25346 }
25347 self->private_impl.f_block_size = 0;
25348 self->private_impl.f_decode_huffman_finished = false;
25349 self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[0] & 7)];
25350 self->private_impl.f_decode_huffman_ticks = 50;
25351 self->private_impl.f_decode_huffman_section = 0;
25352 self->private_impl.f_decode_huffman_run_shift = 0;
25353 while ( ! self->private_impl.f_decode_huffman_finished) {
25354 if (a_src) {
25355 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25356 }
25357 v_status = wuffs_bzip2__decoder__decode_huffman_fast(self, a_src);
25358 if (a_src) {
25359 iop_a_src = a_src->data.ptr + a_src->meta.ri;
25360 }
25361 if (wuffs_base__status__is_error(&v_status)) {
25362 status = v_status;
25363 goto exit;
25364 } else if (self->private_impl.f_decode_huffman_finished) {
25365 goto label__1__break;
25366 }
25367 if (a_src) {
25368 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25369 }
25370 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
25371 status = wuffs_bzip2__decoder__decode_huffman_slow(self, a_src);
25372 if (a_src) {
25373 iop_a_src = a_src->data.ptr + a_src->meta.ri;
25374 }
25375 if (status.repr) {
25376 goto suspend;
25377 }
25378 }
25379 label__1__break:;
25380 wuffs_bzip2__decoder__invert_bwt(self);
25381 self->private_impl.f_block_checksum_have = 4294967295;
25382 if (self->private_impl.f_original_pointer >= self->private_impl.f_block_size) {
25383 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
25384 goto exit;
25385 }
25386 self->private_impl.f_flush_pointer = (self->private_data.f_bwt[self->private_impl.f_original_pointer] >> 12);
25387 self->private_impl.f_flush_repeat_count = 0;
25388 self->private_impl.f_flush_prev = 0;
25389 while (self->private_impl.f_block_size > 0) {
25390 wuffs_bzip2__decoder__flush_fast(self, a_dst);
25391 if (self->private_impl.f_block_size <= 0) {
25392 goto label__2__break;
25393 }
25394 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
25395 status = wuffs_bzip2__decoder__flush_slow(self, a_dst);
25396 if (status.repr) {
25397 goto suspend;
25398 }
25399 }
25400 label__2__break:;
25401 self->private_impl.f_block_checksum_have ^= 4294967295;
25402 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_block_checksum_have != self->private_impl.f_block_checksum_want)) {
25403 status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum);
25404 goto exit;
25405 }
25406 self->private_impl.f_final_checksum_have = (self->private_impl.f_block_checksum_have ^ ((self->private_impl.f_final_checksum_have >> 31) | ((uint32_t)(self->private_impl.f_final_checksum_have << 1))));
25407 }
25408 label__0__break:;
25409 v_final_checksum_want = 0;
25410 v_i = 0;
25411 while (v_i < 32) {
25412 if (self->private_impl.f_n_bits <= 0) {
25413 {
25414 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
25415 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25416 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25417 goto suspend;
25418 }
25419 uint8_t t_5 = *iop_a_src++;
25420 v_c = t_5;
25421 }
25422 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25423 self->private_impl.f_n_bits = 8;
25424 }
25425 v_final_checksum_want <<= 1;
25426 v_final_checksum_want |= (self->private_impl.f_bits >> 31);
25427 self->private_impl.f_bits <<= 1;
25428 self->private_impl.f_n_bits -= 1;
25429 v_i += 1;
25430 }
25431 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_final_checksum_have != v_final_checksum_want)) {
25432 status = wuffs_base__make_status(wuffs_bzip2__error__bad_checksum);
25433 goto exit;
25434 }
25435
25436 goto ok;
25437 ok:
25438 self->private_impl.p_transform_io[0] = 0;
25439 goto exit;
25440 }
25441
25442 goto suspend;
25443 suspend:
25444 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
25445 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
25446 self->private_data.s_transform_io[0].v_i = v_i;
25447 self->private_data.s_transform_io[0].v_tag = v_tag;
25448 self->private_data.s_transform_io[0].v_final_checksum_want = v_final_checksum_want;
25449
25450 goto exit;
25451 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110025452 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025453 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25454 }
25455
25456 if (wuffs_base__status__is_error(&status)) {
25457 self->private_impl.magic = WUFFS_BASE__DISABLED;
25458 }
25459 return status;
25460}
25461
25462// -------- func bzip2.decoder.prepare_block
25463
25464static wuffs_base__status
25465wuffs_bzip2__decoder__prepare_block(
25466 wuffs_bzip2__decoder* self,
25467 wuffs_base__io_buffer* a_src) {
25468 wuffs_base__status status = wuffs_base__make_status(NULL);
25469
25470 uint8_t v_c = 0;
25471 uint32_t v_i = 0;
25472 uint32_t v_j = 0;
25473 uint32_t v_selector = 0;
25474 uint32_t v_sel_ff = 0;
25475 uint8_t v_movee = 0;
25476 wuffs_base__status v_status = wuffs_base__make_status(NULL);
25477
25478 const uint8_t* iop_a_src = NULL;
25479 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25480 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25481 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110025482 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025483 io0_a_src = a_src->data.ptr;
25484 io1_a_src = io0_a_src + a_src->meta.ri;
25485 iop_a_src = io1_a_src;
25486 io2_a_src = io0_a_src + a_src->meta.wi;
25487 }
25488
25489 uint32_t coro_susp_point = self->private_impl.p_prepare_block[0];
25490 if (coro_susp_point) {
25491 v_i = self->private_data.s_prepare_block[0].v_i;
25492 v_selector = self->private_data.s_prepare_block[0].v_selector;
25493 }
25494 switch (coro_susp_point) {
25495 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
25496
25497 self->private_impl.f_block_checksum_want = 0;
25498 v_i = 0;
25499 while (v_i < 32) {
25500 if (self->private_impl.f_n_bits <= 0) {
25501 {
25502 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
25503 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25504 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25505 goto suspend;
25506 }
25507 uint8_t t_0 = *iop_a_src++;
25508 v_c = t_0;
25509 }
25510 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25511 self->private_impl.f_n_bits = 8;
25512 }
25513 self->private_impl.f_block_checksum_want <<= 1;
25514 self->private_impl.f_block_checksum_want |= (self->private_impl.f_bits >> 31);
25515 self->private_impl.f_bits <<= 1;
25516 self->private_impl.f_n_bits -= 1;
25517 v_i += 1;
25518 }
25519 if (self->private_impl.f_n_bits <= 0) {
25520 {
25521 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
25522 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25523 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25524 goto suspend;
25525 }
25526 uint8_t t_1 = *iop_a_src++;
25527 v_c = t_1;
25528 }
25529 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25530 self->private_impl.f_n_bits = 8;
25531 }
25532 if ((self->private_impl.f_bits >> 31) != 0) {
25533 status = wuffs_base__make_status(wuffs_bzip2__error__unsupported_block_randomization);
25534 goto exit;
25535 }
25536 self->private_impl.f_bits <<= 1;
25537 self->private_impl.f_n_bits -= 1;
25538 self->private_impl.f_original_pointer = 0;
25539 v_i = 0;
25540 while (v_i < 24) {
25541 if (self->private_impl.f_n_bits <= 0) {
25542 {
25543 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
25544 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25545 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25546 goto suspend;
25547 }
25548 uint8_t t_2 = *iop_a_src++;
25549 v_c = t_2;
25550 }
25551 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25552 self->private_impl.f_n_bits = 8;
25553 }
25554 self->private_impl.f_original_pointer <<= 1;
25555 self->private_impl.f_original_pointer |= (self->private_impl.f_bits >> 31);
25556 self->private_impl.f_bits <<= 1;
25557 self->private_impl.f_n_bits -= 1;
25558 v_i += 1;
25559 }
25560 v_i = 0;
25561 while (v_i < 256) {
25562 self->private_data.f_presence[v_i] = 0;
25563 v_i += 1;
25564 }
25565 v_i = 0;
25566 while (v_i < 256) {
25567 if (self->private_impl.f_n_bits <= 0) {
25568 {
25569 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
25570 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25571 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25572 goto suspend;
25573 }
25574 uint8_t t_3 = *iop_a_src++;
25575 v_c = t_3;
25576 }
25577 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25578 self->private_impl.f_n_bits = 8;
25579 }
25580 if ((self->private_impl.f_bits >> 31) != 0) {
25581 self->private_data.f_presence[v_i] = 1;
25582 }
25583 self->private_impl.f_bits <<= 1;
25584 self->private_impl.f_n_bits -= 1;
25585 v_i += 16;
25586 }
25587 self->private_data.f_scratch = 0;
25588 v_i = 0;
25589 label__0__continue:;
25590 while (v_i < 256) {
25591 if (self->private_data.f_presence[v_i] == 0) {
25592 v_i += 16;
25593 goto label__0__continue;
25594 }
25595 while (true) {
25596 if (self->private_impl.f_n_bits <= 0) {
25597 {
25598 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
25599 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25600 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25601 goto suspend;
25602 }
25603 uint8_t t_4 = *iop_a_src++;
25604 v_c = t_4;
25605 }
25606 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25607 self->private_impl.f_n_bits = 8;
25608 }
25609 self->private_data.f_scratch += (self->private_impl.f_bits >> 31);
25610 self->private_data.f_presence[(v_i & 255)] = ((uint8_t)((self->private_impl.f_bits >> 31)));
25611 self->private_impl.f_bits <<= 1;
25612 self->private_impl.f_n_bits -= 1;
25613 v_i += 1;
25614 if ((v_i & 15) == 0) {
25615 goto label__1__break;
25616 }
25617 }
25618 label__1__break:;
25619 }
25620 if ((self->private_data.f_scratch < 1) || (256 < self->private_data.f_scratch)) {
25621 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25622 goto exit;
25623 }
25624 self->private_impl.f_num_symbols = (self->private_data.f_scratch + 2);
25625 self->private_data.f_scratch = 0;
25626 v_i = 0;
25627 while (v_i < 3) {
25628 if (self->private_impl.f_n_bits <= 0) {
25629 {
25630 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
25631 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25632 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25633 goto suspend;
25634 }
25635 uint8_t t_5 = *iop_a_src++;
25636 v_c = t_5;
25637 }
25638 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25639 self->private_impl.f_n_bits = 8;
25640 }
25641 self->private_data.f_scratch <<= 1;
25642 self->private_data.f_scratch |= (self->private_impl.f_bits >> 31);
25643 self->private_impl.f_bits <<= 1;
25644 self->private_impl.f_n_bits -= 1;
25645 v_i += 1;
25646 }
25647 if ((self->private_data.f_scratch < 2) || (6 < self->private_data.f_scratch)) {
25648 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25649 goto exit;
25650 }
25651 self->private_impl.f_num_huffman_codes = self->private_data.f_scratch;
25652 self->private_data.f_scratch = 0;
25653 v_i = 0;
25654 while (v_i < 15) {
25655 if (self->private_impl.f_n_bits <= 0) {
25656 {
25657 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
25658 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25659 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25660 goto suspend;
25661 }
25662 uint8_t t_6 = *iop_a_src++;
25663 v_c = t_6;
25664 }
25665 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25666 self->private_impl.f_n_bits = 8;
25667 }
25668 self->private_data.f_scratch <<= 1;
25669 self->private_data.f_scratch |= (self->private_impl.f_bits >> 31);
25670 self->private_impl.f_bits <<= 1;
25671 self->private_impl.f_n_bits -= 1;
25672 v_i += 1;
25673 }
25674 if ((self->private_data.f_scratch < 1) || (18001 < self->private_data.f_scratch)) {
25675 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25676 goto exit;
25677 }
25678 self->private_impl.f_num_sections = self->private_data.f_scratch;
25679 v_i = 0;
25680 while (v_i < self->private_impl.f_num_huffman_codes) {
25681 self->private_data.f_mtft[v_i] = ((uint8_t)(v_i));
25682 v_i += 1;
25683 }
25684 v_i = 0;
25685 while (v_i < self->private_impl.f_num_sections) {
25686 v_selector = 0;
25687 while (true) {
25688 if (self->private_impl.f_n_bits <= 0) {
25689 {
25690 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
25691 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25692 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25693 goto suspend;
25694 }
25695 uint8_t t_7 = *iop_a_src++;
25696 v_c = t_7;
25697 }
25698 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25699 self->private_impl.f_n_bits = 8;
25700 }
25701 if ((self->private_impl.f_bits >> 31) == 0) {
25702 self->private_impl.f_bits <<= 1;
25703 self->private_impl.f_n_bits -= 1;
25704 goto label__2__break;
25705 }
25706 self->private_impl.f_bits <<= 1;
25707 self->private_impl.f_n_bits -= 1;
25708 v_selector += 1;
25709 if (v_selector >= self->private_impl.f_num_huffman_codes) {
25710 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25711 goto exit;
25712 }
25713 }
25714 label__2__break:;
25715 if (v_selector == 0) {
25716 self->private_data.f_huffman_selectors[v_i] = self->private_data.f_mtft[0];
25717 } else {
25718 v_sel_ff = (v_selector & 255);
25719 v_movee = self->private_data.f_mtft[v_sel_ff];
25720 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1 + v_sel_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_sel_ff));
25721 self->private_data.f_mtft[0] = v_movee;
25722 self->private_data.f_huffman_selectors[v_i] = v_movee;
25723 }
25724 v_i += 1;
25725 }
25726 v_i = 0;
25727 while (v_i < self->private_impl.f_num_huffman_codes) {
25728 if (a_src) {
25729 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25730 }
25731 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
25732 status = wuffs_bzip2__decoder__read_code_lengths(self, a_src);
25733 if (a_src) {
25734 iop_a_src = a_src->data.ptr + a_src->meta.ri;
25735 }
25736 if (status.repr) {
25737 goto suspend;
25738 }
25739 v_status = wuffs_bzip2__decoder__build_huffman_tree(self, v_i);
25740 if (wuffs_base__status__is_error(&v_status)) {
25741 status = v_status;
25742 goto exit;
25743 }
25744 wuffs_bzip2__decoder__build_huffman_table(self, v_i);
25745 v_i += 1;
25746 }
25747 v_i = 0;
25748 v_j = 0;
25749 while (v_i < 256) {
25750 if (self->private_data.f_presence[v_i] != 0) {
25751 self->private_data.f_mtft[(v_j & 255)] = ((uint8_t)(v_i));
25752 v_j += 1;
25753 }
25754 v_i += 1;
25755 }
25756 v_i = 0;
25757 while (v_i < 256) {
25758 self->private_data.f_letter_counts[v_i] = 0;
25759 v_i += 1;
25760 }
25761
25762 goto ok;
25763 ok:
25764 self->private_impl.p_prepare_block[0] = 0;
25765 goto exit;
25766 }
25767
25768 goto suspend;
25769 suspend:
25770 self->private_impl.p_prepare_block[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
25771 self->private_data.s_prepare_block[0].v_i = v_i;
25772 self->private_data.s_prepare_block[0].v_selector = v_selector;
25773
25774 goto exit;
25775 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110025776 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025777 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25778 }
25779
25780 return status;
25781}
25782
25783// -------- func bzip2.decoder.read_code_lengths
25784
25785static wuffs_base__status
25786wuffs_bzip2__decoder__read_code_lengths(
25787 wuffs_bzip2__decoder* self,
25788 wuffs_base__io_buffer* a_src) {
25789 wuffs_base__status status = wuffs_base__make_status(NULL);
25790
25791 uint8_t v_c = 0;
25792 uint32_t v_i = 0;
25793 uint32_t v_code_length = 0;
25794
25795 const uint8_t* iop_a_src = NULL;
25796 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25797 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
25798 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110025799 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025800 io0_a_src = a_src->data.ptr;
25801 io1_a_src = io0_a_src + a_src->meta.ri;
25802 iop_a_src = io1_a_src;
25803 io2_a_src = io0_a_src + a_src->meta.wi;
25804 }
25805
25806 uint32_t coro_susp_point = self->private_impl.p_read_code_lengths[0];
25807 if (coro_susp_point) {
25808 v_i = self->private_data.s_read_code_lengths[0].v_i;
25809 v_code_length = self->private_data.s_read_code_lengths[0].v_code_length;
25810 }
25811 switch (coro_susp_point) {
25812 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
25813
25814 self->private_impl.f_code_lengths_bitmask = 0;
25815 v_i = 0;
25816 while (v_i < 5) {
25817 if (self->private_impl.f_n_bits <= 0) {
25818 {
25819 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
25820 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25821 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25822 goto suspend;
25823 }
25824 uint8_t t_0 = *iop_a_src++;
25825 v_c = t_0;
25826 }
25827 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25828 self->private_impl.f_n_bits = 8;
25829 }
25830 v_code_length <<= 1;
25831 v_code_length |= (self->private_impl.f_bits >> 31);
25832 self->private_impl.f_bits <<= 1;
25833 self->private_impl.f_n_bits -= 1;
25834 v_i += 1;
25835 }
25836 v_i = 0;
25837 while (v_i < self->private_impl.f_num_symbols) {
25838 while (true) {
25839 if ((v_code_length < 1) || (20 < v_code_length)) {
25840 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_header);
25841 goto exit;
25842 }
25843 if (self->private_impl.f_n_bits <= 0) {
25844 {
25845 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
25846 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25847 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25848 goto suspend;
25849 }
25850 uint8_t t_1 = *iop_a_src++;
25851 v_c = t_1;
25852 }
25853 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25854 self->private_impl.f_n_bits = 8;
25855 }
25856 if ((self->private_impl.f_bits >> 31) == 0) {
25857 self->private_impl.f_bits <<= 1;
25858 self->private_impl.f_n_bits -= 1;
25859 goto label__0__break;
25860 }
25861 self->private_impl.f_bits <<= 1;
25862 self->private_impl.f_n_bits -= 1;
25863 if (self->private_impl.f_n_bits <= 0) {
25864 {
25865 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
25866 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
25867 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
25868 goto suspend;
25869 }
25870 uint8_t t_2 = *iop_a_src++;
25871 v_c = t_2;
25872 }
25873 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
25874 self->private_impl.f_n_bits = 8;
25875 }
25876 if ((self->private_impl.f_bits >> 31) == 0) {
25877 v_code_length += 1;
25878 } else {
25879 v_code_length -= 1;
25880 }
25881 self->private_impl.f_bits <<= 1;
25882 self->private_impl.f_n_bits -= 1;
25883 }
25884 label__0__break:;
25885 self->private_impl.f_code_lengths_bitmask |= (((uint32_t)(1)) << (v_code_length & 31));
25886 self->private_data.f_bwt[v_i] = v_code_length;
25887 v_i += 1;
25888 }
25889
25890 goto ok;
25891 ok:
25892 self->private_impl.p_read_code_lengths[0] = 0;
25893 goto exit;
25894 }
25895
25896 goto suspend;
25897 suspend:
25898 self->private_impl.p_read_code_lengths[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
25899 self->private_data.s_read_code_lengths[0].v_i = v_i;
25900 self->private_data.s_read_code_lengths[0].v_code_length = v_code_length;
25901
25902 goto exit;
25903 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110025904 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100025905 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
25906 }
25907
25908 return status;
25909}
25910
25911// -------- func bzip2.decoder.build_huffman_tree
25912
25913static wuffs_base__status
25914wuffs_bzip2__decoder__build_huffman_tree(
25915 wuffs_bzip2__decoder* self,
25916 uint32_t a_which) {
25917 uint32_t v_code_length = 0;
25918 uint32_t v_symbol_index = 0;
Nigel Taoa8205c22022-07-10 16:01:15 +100025919 uint32_t v_num_branch_nodes = 0;
Nigel Tao123a5c62022-06-03 14:17:20 +100025920 uint32_t v_stack_height = 0;
25921 uint32_t v_stack_values[21] = {0};
25922 uint32_t v_node_index = 0;
25923 uint16_t v_leaf_value = 0;
25924
25925 self->private_data.f_huffman_trees[a_which][0][0] = 0;
25926 self->private_data.f_huffman_trees[a_which][0][1] = 0;
Nigel Taoa8205c22022-07-10 16:01:15 +100025927 v_num_branch_nodes = 1;
Nigel Tao123a5c62022-06-03 14:17:20 +100025928 v_stack_height = 1;
25929 v_stack_values[0] = 0;
25930 v_code_length = 1;
25931 label__0__continue:;
25932 while (v_code_length <= 20) {
25933 if ((self->private_impl.f_code_lengths_bitmask & (((uint32_t)(1)) << v_code_length)) == 0) {
25934 v_code_length += 1;
25935 goto label__0__continue;
25936 }
25937 v_symbol_index = 0;
25938 label__1__continue:;
25939 while (v_symbol_index < self->private_impl.f_num_symbols) {
25940 if (self->private_data.f_bwt[v_symbol_index] != v_code_length) {
25941 v_symbol_index += 1;
25942 goto label__1__continue;
25943 }
25944 while (true) {
25945 if (v_stack_height <= 0) {
25946 return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_over_subscribed);
25947 } else if (v_stack_height >= v_code_length) {
25948 goto label__2__break;
25949 }
25950 v_node_index = v_stack_values[(v_stack_height - 1)];
25951 if (self->private_data.f_huffman_trees[a_which][v_node_index][0] == 0) {
Nigel Taoa8205c22022-07-10 16:01:15 +100025952 self->private_data.f_huffman_trees[a_which][v_node_index][0] = ((uint16_t)(v_num_branch_nodes));
Nigel Tao123a5c62022-06-03 14:17:20 +100025953 } else {
Nigel Taoa8205c22022-07-10 16:01:15 +100025954 self->private_data.f_huffman_trees[a_which][v_node_index][1] = ((uint16_t)(v_num_branch_nodes));
Nigel Tao123a5c62022-06-03 14:17:20 +100025955 }
Nigel Taoa8205c22022-07-10 16:01:15 +100025956 if (v_num_branch_nodes >= 257) {
25957 return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed);
Nigel Tao123a5c62022-06-03 14:17:20 +100025958 }
Nigel Taoa8205c22022-07-10 16:01:15 +100025959 v_stack_values[v_stack_height] = v_num_branch_nodes;
25960 self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][0] = 0;
25961 self->private_data.f_huffman_trees[a_which][v_num_branch_nodes][1] = 0;
25962 v_num_branch_nodes += 1;
Nigel Tao123a5c62022-06-03 14:17:20 +100025963 v_stack_height += 1;
25964 }
25965 label__2__break:;
25966 v_node_index = v_stack_values[(v_stack_height - 1)];
25967 if (v_symbol_index < 2) {
Nigel Taoa8205c22022-07-10 16:01:15 +100025968 v_leaf_value = ((uint16_t)((769 + v_symbol_index)));
Nigel Tao123a5c62022-06-03 14:17:20 +100025969 } else if ((v_symbol_index + 1) < self->private_impl.f_num_symbols) {
Nigel Taoa8205c22022-07-10 16:01:15 +100025970 v_leaf_value = ((uint16_t)((511 + v_symbol_index)));
Nigel Tao123a5c62022-06-03 14:17:20 +100025971 } else {
Nigel Taoa8205c22022-07-10 16:01:15 +100025972 v_leaf_value = 768;
Nigel Tao123a5c62022-06-03 14:17:20 +100025973 }
25974 if (self->private_data.f_huffman_trees[a_which][v_node_index][0] == 0) {
25975 self->private_data.f_huffman_trees[a_which][v_node_index][0] = v_leaf_value;
25976 } else {
25977 self->private_data.f_huffman_trees[a_which][v_node_index][1] = v_leaf_value;
25978 v_stack_height -= 1;
25979 while (v_stack_height > 0) {
25980 v_node_index = v_stack_values[(v_stack_height - 1)];
25981 if (self->private_data.f_huffman_trees[a_which][v_node_index][1] == 0) {
25982 goto label__3__break;
25983 }
25984 v_stack_height -= 1;
25985 }
25986 label__3__break:;
25987 }
25988 v_symbol_index += 1;
25989 }
25990 v_code_length += 1;
25991 }
25992 if (v_stack_height != 0) {
25993 return wuffs_base__make_status(wuffs_bzip2__error__bad_huffman_code_under_subscribed);
25994 }
25995 return wuffs_base__make_status(NULL);
25996}
25997
25998// -------- func bzip2.decoder.build_huffman_table
25999
26000static wuffs_base__empty_struct
26001wuffs_bzip2__decoder__build_huffman_table(
26002 wuffs_bzip2__decoder* self,
26003 uint32_t a_which) {
26004 uint32_t v_i = 0;
26005 uint32_t v_bits = 0;
26006 uint16_t v_n_bits = 0;
26007 uint16_t v_child = 0;
26008
26009 while (v_i < 256) {
26010 v_bits = (v_i << 24);
26011 v_n_bits = 0;
26012 v_child = 0;
Nigel Taoa8205c22022-07-10 16:01:15 +100026013 while ((v_child < 257) && (v_n_bits < 8)) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026014 v_child = self->private_data.f_huffman_trees[a_which][v_child][(v_bits >> 31)];
26015 v_bits <<= 1;
26016#if defined(__GNUC__)
26017#pragma GCC diagnostic push
26018#pragma GCC diagnostic ignored "-Wconversion"
26019#endif
26020 v_n_bits += 1;
26021#if defined(__GNUC__)
26022#pragma GCC diagnostic pop
26023#endif
26024 }
26025 self->private_data.f_huffman_tables[a_which][v_i] = ((uint16_t)((v_child | (v_n_bits << 12))));
26026 v_i += 1;
26027 }
26028 return wuffs_base__make_empty_struct();
26029}
26030
26031// -------- func bzip2.decoder.invert_bwt
26032
26033static wuffs_base__empty_struct
26034wuffs_bzip2__decoder__invert_bwt(
26035 wuffs_bzip2__decoder* self) {
26036 uint32_t v_i = 0;
26037 uint32_t v_letter = 0;
26038 uint32_t v_sum = 0;
26039 uint32_t v_old_sum = 0;
26040
26041 v_sum = 0;
26042 v_i = 0;
26043 while (v_i < 256) {
26044 v_old_sum = v_sum;
26045 v_sum += self->private_data.f_letter_counts[v_i];
26046 self->private_data.f_letter_counts[v_i] = v_old_sum;
26047 v_i += 1;
26048 }
26049 v_i = 0;
26050 while (v_i < self->private_impl.f_block_size) {
26051 v_letter = (self->private_data.f_bwt[v_i] & 255);
26052 self->private_data.f_bwt[(self->private_data.f_letter_counts[v_letter] & 1048575)] |= (v_i << 12);
26053 self->private_data.f_letter_counts[v_letter] += 1;
26054 v_i += 1;
26055 }
26056 return wuffs_base__make_empty_struct();
26057}
26058
26059// -------- func bzip2.decoder.flush_fast
26060
26061static wuffs_base__empty_struct
26062wuffs_bzip2__decoder__flush_fast(
26063 wuffs_bzip2__decoder* self,
26064 wuffs_base__io_buffer* a_dst) {
26065 uint32_t v_flush_pointer = 0;
26066 uint32_t v_flush_repeat_count = 0;
26067 uint8_t v_flush_prev = 0;
26068 uint32_t v_block_checksum_have = 0;
26069 uint32_t v_block_size = 0;
26070 uint32_t v_entry = 0;
26071 uint8_t v_curr = 0;
26072
26073 uint8_t* iop_a_dst = NULL;
26074 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26075 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26076 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026077 if (a_dst && a_dst->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026078 io0_a_dst = a_dst->data.ptr;
26079 io1_a_dst = io0_a_dst + a_dst->meta.wi;
26080 iop_a_dst = io1_a_dst;
26081 io2_a_dst = io0_a_dst + a_dst->data.len;
26082 if (a_dst->meta.closed) {
26083 io2_a_dst = iop_a_dst;
26084 }
26085 }
26086
26087 v_flush_pointer = self->private_impl.f_flush_pointer;
26088 v_flush_repeat_count = self->private_impl.f_flush_repeat_count;
26089 v_flush_prev = self->private_impl.f_flush_prev;
26090 v_block_checksum_have = self->private_impl.f_block_checksum_have;
26091 v_block_size = self->private_impl.f_block_size;
26092 while ((v_block_size > 0) && (((uint64_t)(io2_a_dst - iop_a_dst)) >= 255)) {
26093 if (v_flush_repeat_count < 4) {
26094 v_entry = self->private_data.f_bwt[v_flush_pointer];
26095 v_curr = ((uint8_t)((v_entry & 255)));
26096 v_flush_pointer = (v_entry >> 12);
26097 if (v_curr == v_flush_prev) {
26098 v_flush_repeat_count += 1;
26099 } else {
26100 v_flush_repeat_count = 1;
26101 }
26102 v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24))) ^ v_curr)] ^ ((uint32_t)(v_block_checksum_have << 8)));
26103 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_curr), iop_a_dst += 1);
26104 v_flush_prev = v_curr;
26105 v_block_size -= 1;
26106 } else {
26107 v_entry = self->private_data.f_bwt[v_flush_pointer];
26108 v_curr = ((uint8_t)((v_entry & 255)));
26109 v_flush_pointer = (v_entry >> 12);
26110 v_flush_repeat_count = ((uint32_t)(v_curr));
26111 while (v_flush_repeat_count > 0) {
26112 v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24))) ^ v_flush_prev)] ^ ((uint32_t)(v_block_checksum_have << 8)));
26113 if (((uint64_t)(io2_a_dst - iop_a_dst)) > 0) {
26114 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_flush_prev), iop_a_dst += 1);
26115 }
26116 v_flush_repeat_count -= 1;
26117 }
26118 v_flush_repeat_count = 0;
26119 v_flush_prev = v_curr;
26120 v_block_size -= 1;
26121 }
26122 }
26123 self->private_impl.f_flush_pointer = v_flush_pointer;
26124 self->private_impl.f_flush_repeat_count = v_flush_repeat_count;
26125 self->private_impl.f_flush_prev = v_flush_prev;
26126 self->private_impl.f_block_checksum_have = v_block_checksum_have;
26127 if (v_block_size <= 900000) {
26128 self->private_impl.f_block_size = v_block_size;
26129 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110026130 if (a_dst && a_dst->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026131 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
26132 }
26133
26134 return wuffs_base__make_empty_struct();
26135}
26136
26137// -------- func bzip2.decoder.flush_slow
26138
26139static wuffs_base__status
26140wuffs_bzip2__decoder__flush_slow(
26141 wuffs_bzip2__decoder* self,
26142 wuffs_base__io_buffer* a_dst) {
26143 wuffs_base__status status = wuffs_base__make_status(NULL);
26144
26145 uint32_t v_flush_pointer = 0;
26146 uint32_t v_flush_repeat_count = 0;
26147 uint8_t v_flush_prev = 0;
26148 uint32_t v_block_checksum_have = 0;
26149 uint32_t v_block_size = 0;
26150 uint32_t v_entry = 0;
26151 uint8_t v_curr = 0;
26152
26153 uint8_t* iop_a_dst = NULL;
26154 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26155 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26156 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026157 if (a_dst && a_dst->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026158 io0_a_dst = a_dst->data.ptr;
26159 io1_a_dst = io0_a_dst + a_dst->meta.wi;
26160 iop_a_dst = io1_a_dst;
26161 io2_a_dst = io0_a_dst + a_dst->data.len;
26162 if (a_dst->meta.closed) {
26163 io2_a_dst = iop_a_dst;
26164 }
26165 }
26166
26167 uint32_t coro_susp_point = self->private_impl.p_flush_slow[0];
26168 if (coro_susp_point) {
26169 v_flush_pointer = self->private_data.s_flush_slow[0].v_flush_pointer;
26170 v_flush_repeat_count = self->private_data.s_flush_slow[0].v_flush_repeat_count;
26171 v_flush_prev = self->private_data.s_flush_slow[0].v_flush_prev;
26172 v_block_checksum_have = self->private_data.s_flush_slow[0].v_block_checksum_have;
26173 v_block_size = self->private_data.s_flush_slow[0].v_block_size;
26174 v_curr = self->private_data.s_flush_slow[0].v_curr;
26175 }
26176 switch (coro_susp_point) {
26177 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26178
26179 v_flush_pointer = self->private_impl.f_flush_pointer;
26180 v_flush_repeat_count = self->private_impl.f_flush_repeat_count;
26181 v_flush_prev = self->private_impl.f_flush_prev;
26182 v_block_checksum_have = self->private_impl.f_block_checksum_have;
26183 v_block_size = self->private_impl.f_block_size;
26184 while ((v_block_size > 0) && ! (self->private_impl.p_flush_slow[0] != 0)) {
26185 if (v_flush_repeat_count < 4) {
26186 v_entry = self->private_data.f_bwt[v_flush_pointer];
26187 v_curr = ((uint8_t)((v_entry & 255)));
26188 v_flush_pointer = (v_entry >> 12);
26189 if (v_curr == v_flush_prev) {
26190 v_flush_repeat_count += 1;
26191 } else {
26192 v_flush_repeat_count = 1;
26193 }
26194 v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24))) ^ v_curr)] ^ ((uint32_t)(v_block_checksum_have << 8)));
26195 self->private_data.s_flush_slow[0].scratch = v_curr;
26196 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
26197 if (iop_a_dst == io2_a_dst) {
26198 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26199 goto suspend;
26200 }
26201 *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow[0].scratch));
26202 v_flush_prev = v_curr;
26203 v_block_size -= 1;
26204 } else {
26205 v_entry = self->private_data.f_bwt[v_flush_pointer];
26206 v_curr = ((uint8_t)((v_entry & 255)));
26207 v_flush_pointer = (v_entry >> 12);
26208 v_flush_repeat_count = ((uint32_t)(v_curr));
26209 while (v_flush_repeat_count > 0) {
26210 v_block_checksum_have = (WUFFS_BZIP2__REV_CRC32_TABLE[(((uint8_t)((v_block_checksum_have >> 24))) ^ v_flush_prev)] ^ ((uint32_t)(v_block_checksum_have << 8)));
26211 self->private_data.s_flush_slow[0].scratch = v_flush_prev;
26212 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
26213 if (iop_a_dst == io2_a_dst) {
26214 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26215 goto suspend;
26216 }
26217 *iop_a_dst++ = ((uint8_t)(self->private_data.s_flush_slow[0].scratch));
26218 v_flush_repeat_count -= 1;
26219 }
26220 v_flush_repeat_count = 0;
26221 v_flush_prev = v_curr;
26222 v_block_size -= 1;
26223 }
26224 }
26225 self->private_impl.f_flush_pointer = v_flush_pointer;
26226 self->private_impl.f_flush_repeat_count = v_flush_repeat_count;
26227 self->private_impl.f_flush_prev = v_flush_prev;
26228 self->private_impl.f_block_checksum_have = v_block_checksum_have;
26229 if (v_block_size <= 900000) {
26230 self->private_impl.f_block_size = v_block_size;
26231 }
26232
26233 goto ok;
26234 ok:
26235 self->private_impl.p_flush_slow[0] = 0;
26236 goto exit;
26237 }
26238
26239 goto suspend;
26240 suspend:
26241 self->private_impl.p_flush_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26242 self->private_data.s_flush_slow[0].v_flush_pointer = v_flush_pointer;
26243 self->private_data.s_flush_slow[0].v_flush_repeat_count = v_flush_repeat_count;
26244 self->private_data.s_flush_slow[0].v_flush_prev = v_flush_prev;
26245 self->private_data.s_flush_slow[0].v_block_checksum_have = v_block_checksum_have;
26246 self->private_data.s_flush_slow[0].v_block_size = v_block_size;
26247 self->private_data.s_flush_slow[0].v_curr = v_curr;
26248
26249 goto exit;
26250 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110026251 if (a_dst && a_dst->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026252 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
26253 }
26254
26255 return status;
26256}
26257
26258// -------- func bzip2.decoder.decode_huffman_fast
26259
26260static wuffs_base__status
26261wuffs_bzip2__decoder__decode_huffman_fast(
26262 wuffs_bzip2__decoder* self,
26263 wuffs_base__io_buffer* a_src) {
26264 wuffs_base__status status = wuffs_base__make_status(NULL);
26265
26266 uint32_t v_bits = 0;
26267 uint32_t v_n_bits = 0;
26268 uint32_t v_block_size = 0;
26269 uint8_t v_which = 0;
26270 uint32_t v_ticks = 0;
26271 uint32_t v_section = 0;
26272 uint32_t v_run_shift = 0;
26273 uint16_t v_table_entry = 0;
26274 uint16_t v_child = 0;
26275 uint32_t v_child_ff = 0;
26276 uint32_t v_i = 0;
26277 uint32_t v_j = 0;
26278 uint32_t v_output = 0;
26279 uint32_t v_run = 0;
26280 uint32_t v_mtft0 = 0;
26281
26282 const uint8_t* iop_a_src = NULL;
26283 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26284 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26285 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026286 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026287 io0_a_src = a_src->data.ptr;
26288 io1_a_src = io0_a_src + a_src->meta.ri;
26289 iop_a_src = io1_a_src;
26290 io2_a_src = io0_a_src + a_src->meta.wi;
26291 }
26292
26293 v_bits = self->private_impl.f_bits;
26294 v_n_bits = self->private_impl.f_n_bits;
26295 v_block_size = self->private_impl.f_block_size;
26296 v_which = self->private_impl.f_decode_huffman_which;
26297 v_ticks = self->private_impl.f_decode_huffman_ticks;
26298 v_section = self->private_impl.f_decode_huffman_section;
26299 v_run_shift = self->private_impl.f_decode_huffman_run_shift;
26300 label__outer__continue:;
26301 while (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
26302 if (v_ticks > 0) {
26303 v_ticks -= 1;
26304 } else {
26305 v_ticks = 49;
26306 v_section += 1;
Nigel Taoa8205c22022-07-10 16:01:15 +100026307 if (v_section >= self->private_impl.f_num_sections) {
26308 status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections);
26309 goto exit;
26310 }
Nigel Tao123a5c62022-06-03 14:17:20 +100026311 v_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[(v_section & 32767)] & 7)];
26312 }
26313 v_bits |= (wuffs_base__peek_u32be__no_bounds_check(iop_a_src) >> v_n_bits);
26314 iop_a_src += ((31 - v_n_bits) >> 3);
26315 v_n_bits |= 24;
26316 v_table_entry = self->private_data.f_huffman_tables[v_which][(v_bits >> 24)];
26317 v_bits <<= (v_table_entry >> 12);
26318 v_n_bits -= ((uint32_t)((v_table_entry >> 12)));
Nigel Taoa8205c22022-07-10 16:01:15 +100026319 v_child = (v_table_entry & 1023);
26320 while (v_child < 257) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026321 v_child = self->private_data.f_huffman_trees[v_which][v_child][(v_bits >> 31)];
26322 v_bits <<= 1;
26323 if (v_n_bits <= 0) {
26324 status = wuffs_base__make_status(wuffs_bzip2__error__internal_error_inconsistent_huffman_decoder_state);
26325 goto exit;
26326 }
26327 v_n_bits -= 1;
26328 }
Nigel Taoa8205c22022-07-10 16:01:15 +100026329 if (v_child < 768) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026330 v_child_ff = ((uint32_t)((v_child & 255)));
26331 v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff]));
26332 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1 + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff));
26333 self->private_data.f_mtft[0] = ((uint8_t)(v_output));
26334 self->private_data.f_letter_counts[v_output] += 1;
26335 self->private_data.f_bwt[v_block_size] = v_output;
26336 if (v_block_size >= self->private_impl.f_max_incl_block_size) {
26337 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26338 goto exit;
26339 }
26340 v_block_size += 1;
26341 v_run_shift = 0;
26342 goto label__outer__continue;
Nigel Taoa8205c22022-07-10 16:01:15 +100026343 } else if (v_child == 768) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026344 self->private_impl.f_decode_huffman_finished = true;
26345 goto label__outer__break;
26346 }
26347 if (v_run_shift >= 23) {
26348 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26349 goto exit;
26350 }
Nigel Taoa8205c22022-07-10 16:01:15 +100026351 v_run = ((((uint32_t)(v_child)) & 3) << v_run_shift);
Nigel Tao123a5c62022-06-03 14:17:20 +100026352 v_run_shift += 1;
26353 v_i = v_block_size;
26354 v_j = (v_run + v_block_size);
26355 if (v_j > self->private_impl.f_max_incl_block_size) {
26356 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26357 goto exit;
26358 }
26359 v_block_size = v_j;
26360 v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0]));
26361 self->private_data.f_letter_counts[v_mtft0] += v_run;
26362 while (v_i < v_j) {
26363 self->private_data.f_bwt[v_i] = v_mtft0;
26364 v_i += 1;
26365 }
26366 }
26367 label__outer__break:;
26368 self->private_impl.f_bits = v_bits;
26369 self->private_impl.f_n_bits = v_n_bits;
26370 self->private_impl.f_block_size = v_block_size;
26371 self->private_impl.f_decode_huffman_which = v_which;
26372 self->private_impl.f_decode_huffman_ticks = v_ticks;
26373 self->private_impl.f_decode_huffman_section = v_section;
26374 self->private_impl.f_decode_huffman_run_shift = v_run_shift;
26375 status = wuffs_base__make_status(NULL);
26376 goto ok;
26377
26378 ok:
26379 goto exit;
26380 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110026381 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026382 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26383 }
26384
26385 return status;
26386}
26387
26388// -------- func bzip2.decoder.decode_huffman_slow
26389
26390static wuffs_base__status
26391wuffs_bzip2__decoder__decode_huffman_slow(
26392 wuffs_bzip2__decoder* self,
26393 wuffs_base__io_buffer* a_src) {
26394 wuffs_base__status status = wuffs_base__make_status(NULL);
26395
26396 uint8_t v_c = 0;
26397 uint32_t v_node_index = 0;
26398 uint16_t v_child = 0;
26399 uint32_t v_child_ff = 0;
26400 uint32_t v_i = 0;
26401 uint32_t v_j = 0;
26402 uint32_t v_output = 0;
26403 uint32_t v_run = 0;
26404 uint32_t v_mtft0 = 0;
26405
26406 const uint8_t* iop_a_src = NULL;
26407 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26408 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26409 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026410 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026411 io0_a_src = a_src->data.ptr;
26412 io1_a_src = io0_a_src + a_src->meta.ri;
26413 iop_a_src = io1_a_src;
26414 io2_a_src = io0_a_src + a_src->meta.wi;
26415 }
26416
26417 uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0];
26418 if (coro_susp_point) {
26419 v_node_index = self->private_data.s_decode_huffman_slow[0].v_node_index;
26420 }
26421 switch (coro_susp_point) {
26422 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26423
26424 while ( ! (self->private_impl.p_decode_huffman_slow[0] != 0)) {
26425 if (self->private_impl.f_decode_huffman_ticks > 0) {
26426 self->private_impl.f_decode_huffman_ticks -= 1;
26427 } else {
26428 self->private_impl.f_decode_huffman_ticks = 49;
26429 self->private_impl.f_decode_huffman_section += 1;
Nigel Taoa8205c22022-07-10 16:01:15 +100026430 if (self->private_impl.f_decode_huffman_section >= self->private_impl.f_num_sections) {
26431 status = wuffs_base__make_status(wuffs_bzip2__error__bad_number_of_sections);
26432 goto exit;
26433 }
Nigel Tao123a5c62022-06-03 14:17:20 +100026434 self->private_impl.f_decode_huffman_which = WUFFS_BZIP2__CLAMP_TO_5[(self->private_data.f_huffman_selectors[(self->private_impl.f_decode_huffman_section & 32767)] & 7)];
26435 }
26436 v_node_index = 0;
26437 label__0__continue:;
26438 while (true) {
26439 if (self->private_impl.f_n_bits <= 0) {
26440 {
26441 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
26442 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
26443 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26444 goto suspend;
26445 }
26446 uint8_t t_0 = *iop_a_src++;
26447 v_c = t_0;
26448 }
26449 self->private_impl.f_bits = (((uint32_t)(v_c)) << 24);
26450 self->private_impl.f_n_bits = 8;
26451 }
26452 v_child = self->private_data.f_huffman_trees[self->private_impl.f_decode_huffman_which][v_node_index][(self->private_impl.f_bits >> 31)];
26453 self->private_impl.f_bits <<= 1;
26454 self->private_impl.f_n_bits -= 1;
Nigel Taoa8205c22022-07-10 16:01:15 +100026455 if (v_child < 257) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026456 v_node_index = ((uint32_t)(v_child));
26457 goto label__0__continue;
Nigel Taoa8205c22022-07-10 16:01:15 +100026458 } else if (v_child < 768) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026459 v_child_ff = ((uint32_t)((v_child & 255)));
26460 v_output = ((uint32_t)(self->private_data.f_mtft[v_child_ff]));
26461 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_mtft, 1, (1 + v_child_ff)), wuffs_base__make_slice_u8(self->private_data.f_mtft, v_child_ff));
26462 self->private_data.f_mtft[0] = ((uint8_t)(v_output));
26463 self->private_data.f_letter_counts[v_output] += 1;
26464 self->private_data.f_bwt[self->private_impl.f_block_size] = v_output;
26465 if (self->private_impl.f_block_size >= self->private_impl.f_max_incl_block_size) {
26466 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26467 goto exit;
26468 }
26469 self->private_impl.f_block_size += 1;
26470 self->private_impl.f_decode_huffman_run_shift = 0;
26471 goto label__0__break;
Nigel Taoa8205c22022-07-10 16:01:15 +100026472 } else if (v_child == 768) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026473 self->private_impl.f_decode_huffman_finished = true;
26474 goto label__outer__break;
26475 }
26476 if (self->private_impl.f_decode_huffman_run_shift >= 23) {
26477 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26478 goto exit;
26479 }
Nigel Taoa8205c22022-07-10 16:01:15 +100026480 v_run = ((((uint32_t)(v_child)) & 3) << self->private_impl.f_decode_huffman_run_shift);
Nigel Tao123a5c62022-06-03 14:17:20 +100026481 self->private_impl.f_decode_huffman_run_shift += 1;
26482 v_i = self->private_impl.f_block_size;
26483 v_j = (v_run + self->private_impl.f_block_size);
26484 if (v_j > self->private_impl.f_max_incl_block_size) {
26485 status = wuffs_base__make_status(wuffs_bzip2__error__bad_block_length);
26486 goto exit;
26487 }
26488 self->private_impl.f_block_size = v_j;
26489 v_mtft0 = ((uint32_t)(self->private_data.f_mtft[0]));
26490 self->private_data.f_letter_counts[v_mtft0] += v_run;
26491 while (v_i < v_j) {
26492 self->private_data.f_bwt[v_i] = v_mtft0;
26493 v_i += 1;
26494 }
26495 goto label__0__break;
26496 }
26497 label__0__break:;
26498 }
26499 label__outer__break:;
26500
26501 goto ok;
26502 ok:
26503 self->private_impl.p_decode_huffman_slow[0] = 0;
26504 goto exit;
26505 }
26506
26507 goto suspend;
26508 suspend:
26509 self->private_impl.p_decode_huffman_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
26510 self->private_data.s_decode_huffman_slow[0].v_node_index = v_node_index;
26511
26512 goto exit;
26513 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110026514 if (a_src && a_src->data.ptr) {
Nigel Tao123a5c62022-06-03 14:17:20 +100026515 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
26516 }
26517
26518 return status;
26519}
26520
26521#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BZIP2)
26522
Nigel Taoe360a532021-04-05 22:47:03 +100026523#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
26524
26525// ---------------- Status Codes Implementations
26526
26527const char wuffs_cbor__error__bad_input[] = "#cbor: bad input";
26528const char wuffs_cbor__error__unsupported_recursion_depth[] = "#cbor: unsupported recursion depth";
26529const char wuffs_cbor__error__internal_error_inconsistent_i_o[] = "#cbor: internal error: inconsistent I/O";
26530const char wuffs_cbor__error__internal_error_inconsistent_token_length[] = "#cbor: internal error: inconsistent token length";
26531
26532// ---------------- Private Consts
26533
26534static const uint32_t
26535WUFFS_CBOR__LITERALS[4] WUFFS_BASE__POTENTIALLY_UNUSED = {
26536 8388612, 8388616, 8388610, 8388609,
26537};
26538
26539static const uint8_t
26540WUFFS_CBOR__TOKEN_LENGTHS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
26541 1, 1, 1, 1, 1, 1, 1, 1,
26542 1, 1, 1, 1, 1, 1, 1, 1,
26543 1, 1, 1, 1, 1, 1, 1, 1,
26544 2, 3, 5, 9, 0, 0, 0, 1,
26545};
26546
26547// ---------------- Private Initializer Prototypes
26548
26549// ---------------- Private Function Prototypes
26550
26551// ---------------- VTables
26552
26553const wuffs_base__token_decoder__func_ptrs
26554wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder = {
26555 (wuffs_base__status(*)(void*,
26556 wuffs_base__token_buffer*,
26557 wuffs_base__io_buffer*,
26558 wuffs_base__slice_u8))(&wuffs_cbor__decoder__decode_tokens),
26559 (wuffs_base__empty_struct(*)(void*,
26560 uint32_t,
26561 bool))(&wuffs_cbor__decoder__set_quirk_enabled),
26562 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_cbor__decoder__workbuf_len),
26563};
26564
26565// ---------------- Initializer Implementations
26566
26567wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
26568wuffs_cbor__decoder__initialize(
26569 wuffs_cbor__decoder* self,
26570 size_t sizeof_star_self,
26571 uint64_t wuffs_version,
26572 uint32_t options){
26573 if (!self) {
26574 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
26575 }
26576 if (sizeof(*self) != sizeof_star_self) {
26577 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
26578 }
26579 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
26580 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
26581 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
26582 }
26583
26584 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
26585 // The whole point of this if-check is to detect an uninitialized *self.
26586 // We disable the warning on GCC. Clang-5.0 does not have this warning.
26587#if !defined(__clang__) && defined(__GNUC__)
26588#pragma GCC diagnostic push
26589#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
26590#endif
26591 if (self->private_impl.magic != 0) {
26592 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
26593 }
26594#if !defined(__clang__) && defined(__GNUC__)
26595#pragma GCC diagnostic pop
26596#endif
26597 } else {
26598 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
26599 memset(self, 0, sizeof(*self));
26600 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
26601 } else {
26602 memset(&(self->private_impl), 0, sizeof(self->private_impl));
26603 }
26604 }
26605
26606 self->private_impl.magic = WUFFS_BASE__MAGIC;
26607 self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name =
26608 wuffs_base__token_decoder__vtable_name;
26609 self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers =
26610 (const void*)(&wuffs_cbor__decoder__func_ptrs_for__wuffs_base__token_decoder);
26611 return wuffs_base__make_status(NULL);
26612}
26613
26614wuffs_cbor__decoder*
26615wuffs_cbor__decoder__alloc() {
26616 wuffs_cbor__decoder* x =
26617 (wuffs_cbor__decoder*)(calloc(sizeof(wuffs_cbor__decoder), 1));
26618 if (!x) {
26619 return NULL;
26620 }
26621 if (wuffs_cbor__decoder__initialize(
26622 x, sizeof(wuffs_cbor__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
26623 free(x);
26624 return NULL;
26625 }
26626 return x;
26627}
26628
26629size_t
26630sizeof__wuffs_cbor__decoder() {
26631 return sizeof(wuffs_cbor__decoder);
26632}
26633
26634// ---------------- Function Implementations
26635
26636// -------- func cbor.decoder.set_quirk_enabled
26637
26638WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
26639wuffs_cbor__decoder__set_quirk_enabled(
26640 wuffs_cbor__decoder* self,
26641 uint32_t a_quirk,
26642 bool a_enabled) {
26643 return wuffs_base__make_empty_struct();
26644}
26645
26646// -------- func cbor.decoder.workbuf_len
26647
26648WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
26649wuffs_cbor__decoder__workbuf_len(
26650 const wuffs_cbor__decoder* self) {
26651 if (!self) {
26652 return wuffs_base__utility__empty_range_ii_u64();
26653 }
26654 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
26655 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
26656 return wuffs_base__utility__empty_range_ii_u64();
26657 }
26658
26659 return wuffs_base__utility__empty_range_ii_u64();
26660}
26661
26662// -------- func cbor.decoder.decode_tokens
26663
26664WUFFS_BASE__MAYBE_STATIC wuffs_base__status
26665wuffs_cbor__decoder__decode_tokens(
26666 wuffs_cbor__decoder* self,
26667 wuffs_base__token_buffer* a_dst,
26668 wuffs_base__io_buffer* a_src,
26669 wuffs_base__slice_u8 a_workbuf) {
26670 if (!self) {
26671 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
26672 }
26673 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
26674 return wuffs_base__make_status(
26675 (self->private_impl.magic == WUFFS_BASE__DISABLED)
26676 ? wuffs_base__error__disabled_by_previous_error
26677 : wuffs_base__error__initialize_not_called);
26678 }
26679 if (!a_dst || !a_src) {
26680 self->private_impl.magic = WUFFS_BASE__DISABLED;
26681 return wuffs_base__make_status(wuffs_base__error__bad_argument);
26682 }
26683 if ((self->private_impl.active_coroutine != 0) &&
26684 (self->private_impl.active_coroutine != 1)) {
26685 self->private_impl.magic = WUFFS_BASE__DISABLED;
26686 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
26687 }
26688 self->private_impl.active_coroutine = 0;
26689 wuffs_base__status status = wuffs_base__make_status(NULL);
26690
26691 uint64_t v_string_length = 0;
26692 uint64_t v_n64 = 0;
26693 uint32_t v_depth = 0;
26694 uint32_t v_stack_byte = 0;
26695 uint32_t v_stack_bit = 0;
26696 uint32_t v_stack_val = 0;
26697 uint32_t v_token_length = 0;
26698 uint32_t v_vminor = 0;
26699 uint32_t v_vminor_alt = 0;
26700 uint32_t v_continued = 0;
26701 uint8_t v_c = 0;
26702 uint8_t v_c_major = 0;
26703 uint8_t v_c_minor = 0;
26704 bool v_tagged = false;
26705 uint8_t v_indefinite_string_major_type = 0;
26706
26707 wuffs_base__token* iop_a_dst = NULL;
26708 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26709 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26710 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026711 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100026712 io0_a_dst = a_dst->data.ptr;
26713 io1_a_dst = io0_a_dst + a_dst->meta.wi;
26714 iop_a_dst = io1_a_dst;
26715 io2_a_dst = io0_a_dst + a_dst->data.len;
26716 if (a_dst->meta.closed) {
26717 io2_a_dst = iop_a_dst;
26718 }
26719 }
26720 const uint8_t* iop_a_src = NULL;
26721 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26722 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
26723 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110026724 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100026725 io0_a_src = a_src->data.ptr;
26726 io1_a_src = io0_a_src + a_src->meta.ri;
26727 iop_a_src = io1_a_src;
26728 io2_a_src = io0_a_src + a_src->meta.wi;
26729 }
26730
26731 uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0];
26732 if (coro_susp_point) {
26733 v_string_length = self->private_data.s_decode_tokens[0].v_string_length;
26734 v_depth = self->private_data.s_decode_tokens[0].v_depth;
Nigel Taoe360a532021-04-05 22:47:03 +100026735 v_tagged = self->private_data.s_decode_tokens[0].v_tagged;
26736 v_indefinite_string_major_type = self->private_data.s_decode_tokens[0].v_indefinite_string_major_type;
26737 }
26738 switch (coro_susp_point) {
26739 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
26740
26741 if (self->private_impl.f_end_of_data) {
26742 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
26743 goto ok;
26744 }
26745 label__outer__continue:;
26746 while (true) {
26747 while (true) {
26748 while (true) {
26749 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
26750 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26751 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
26752 goto label__outer__continue;
26753 }
26754 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
26755 if (a_src && a_src->meta.closed) {
26756 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
26757 goto exit;
26758 }
26759 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26760 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
26761 goto label__outer__continue;
26762 }
26763 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
26764 if ((v_indefinite_string_major_type != 0) && (v_indefinite_string_major_type != (v_c >> 5))) {
26765 if (v_c != 255) {
26766 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
26767 goto exit;
26768 }
26769 v_vminor = 4194560;
26770 if (v_indefinite_string_major_type == 3) {
26771 v_vminor |= 19;
26772 }
26773 v_indefinite_string_major_type = 0;
26774 iop_a_src += 1;
26775 *iop_a_dst++ = wuffs_base__make_token(
26776 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26777 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26778 goto label__goto_parsed_a_leaf_value__break;
26779 }
26780 iop_a_src += 1;
26781 v_c_major = ((uint8_t)((v_c >> 5)));
26782 v_c_minor = (v_c & 31);
26783 if (v_c_minor < 24) {
26784 v_string_length = ((uint64_t)(v_c_minor));
26785 } else {
26786 while (true) {
26787 if (v_c_minor == 24) {
26788 if (((uint64_t)(io2_a_src - iop_a_src)) >= 1) {
26789 v_string_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
26790 iop_a_src += 1;
26791 goto label__goto_have_string_length__break;
26792 }
26793 } else if (v_c_minor == 25) {
26794 if (((uint64_t)(io2_a_src - iop_a_src)) >= 2) {
26795 v_string_length = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
26796 iop_a_src += 2;
26797 goto label__goto_have_string_length__break;
26798 }
26799 } else if (v_c_minor == 26) {
26800 if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
26801 v_string_length = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
26802 iop_a_src += 4;
26803 goto label__goto_have_string_length__break;
26804 }
26805 } else if (v_c_minor == 27) {
26806 if (((uint64_t)(io2_a_src - iop_a_src)) >= 8) {
26807 v_string_length = wuffs_base__peek_u64be__no_bounds_check(iop_a_src);
26808 iop_a_src += 8;
26809 goto label__goto_have_string_length__break;
26810 }
26811 } else {
26812 v_string_length = 0;
26813 goto label__goto_have_string_length__break;
26814 }
26815 if (iop_a_src > io1_a_src) {
26816 iop_a_src--;
26817 if (a_src && a_src->meta.closed) {
26818 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
26819 goto exit;
26820 }
26821 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26822 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
Nigel Taoe360a532021-04-05 22:47:03 +100026823 goto label__outer__continue;
26824 }
26825 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
26826 goto exit;
26827 }
26828 label__goto_have_string_length__break:;
26829 }
26830 if (v_c_major == 0) {
26831 if (v_c_minor < 26) {
26832 *iop_a_dst++ = wuffs_base__make_token(
26833 (((uint64_t)((14680064 | ((uint32_t)((v_string_length & 65535)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26834 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26835 goto label__goto_parsed_a_leaf_value__break;
26836 } else if (v_c_minor < 28) {
26837 *iop_a_dst++ = wuffs_base__make_token(
26838 (((uint64_t)((14680064 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26839 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26840 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26841 *iop_a_dst++ = wuffs_base__make_token(
26842 (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
26843 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26844 goto label__goto_parsed_a_leaf_value__break;
26845 }
26846 } else if (v_c_major == 1) {
26847 if (v_c_minor < 26) {
26848 *iop_a_dst++ = wuffs_base__make_token(
26849 (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length & 65535))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26850 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26851 goto label__goto_parsed_a_leaf_value__break;
26852 } else if (v_c_minor < 28) {
26853 if (v_string_length < 9223372036854775808u) {
26854 *iop_a_dst++ = wuffs_base__make_token(
26855 (((uint64_t)((12582912 | (2097151 - ((uint32_t)((v_string_length >> 46))))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26856 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26857 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26858 *iop_a_dst++ = wuffs_base__make_token(
26859 (~((18446744073709551615u - v_string_length) & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
26860 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26861 } else {
26862 *iop_a_dst++ = wuffs_base__make_token(
26863 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
26864 (((uint64_t)(16777216)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26865 (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26866 }
26867 goto label__goto_parsed_a_leaf_value__break;
26868 }
26869 } else if (v_c_major == 2) {
26870 if (v_c_minor < 28) {
26871 if (v_string_length == 0) {
26872 *iop_a_dst++ = wuffs_base__make_token(
26873 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26874 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26875 goto label__goto_parsed_a_leaf_value__break;
26876 }
26877 *iop_a_dst++ = wuffs_base__make_token(
26878 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26879 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26880 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26881 } else if (v_c_minor == 31) {
26882 if (v_indefinite_string_major_type != 0) {
26883 goto label__goto_fail__break;
26884 }
26885 v_indefinite_string_major_type = 2;
26886 *iop_a_dst++ = wuffs_base__make_token(
26887 (((uint64_t)(4194560)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26888 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26889 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26890 goto label__outer__continue;
26891 } else {
26892 goto label__goto_fail__break;
26893 }
26894 label__0__continue:;
26895 while (true) {
26896 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
26897 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26898 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
26899 goto label__0__continue;
26900 }
26901 v_n64 = wuffs_base__u64__min(v_string_length, ((uint64_t)(io2_a_src - iop_a_src)));
26902 v_token_length = ((uint32_t)((v_n64 & 65535)));
26903 if (v_n64 > 65535) {
26904 v_token_length = 65535;
26905 } else if (v_token_length <= 0) {
26906 if (a_src && a_src->meta.closed) {
26907 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
26908 goto exit;
26909 }
26910 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26911 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
26912 goto label__0__continue;
26913 }
26914 if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
26915 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
26916 goto exit;
26917 }
26918 v_string_length -= ((uint64_t)(v_token_length));
26919 v_continued = 0;
26920 if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
26921 v_continued = 1;
26922 }
26923 iop_a_src += v_token_length;
26924 *iop_a_dst++ = wuffs_base__make_token(
26925 (((uint64_t)(4194816)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26926 (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26927 (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26928 if (v_string_length > 0) {
26929 goto label__0__continue;
26930 } else if (v_indefinite_string_major_type > 0) {
26931 goto label__outer__continue;
26932 }
26933 goto label__goto_parsed_a_leaf_value__break;
26934 }
26935 } else if (v_c_major == 3) {
26936 if (v_c_minor < 28) {
26937 if (v_string_length == 0) {
26938 *iop_a_dst++ = wuffs_base__make_token(
26939 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26940 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26941 goto label__goto_parsed_a_leaf_value__break;
26942 }
26943 *iop_a_dst++ = wuffs_base__make_token(
26944 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26945 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26946 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26947 } else if (v_c_minor == 31) {
26948 if (v_indefinite_string_major_type != 0) {
26949 goto label__goto_fail__break;
26950 }
26951 v_indefinite_string_major_type = 3;
26952 *iop_a_dst++ = wuffs_base__make_token(
26953 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26954 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26955 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26956 goto label__outer__continue;
26957 } else {
26958 goto label__goto_fail__break;
26959 }
26960 label__1__continue:;
26961 while (true) {
26962 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
26963 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
26964 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
26965 goto label__1__continue;
26966 }
26967 v_n64 = wuffs_base__u64__min(v_string_length, 65535);
26968 v_n64 = ((uint64_t)(wuffs_base__utf_8__longest_valid_prefix(iop_a_src,
26969 ((size_t)(wuffs_base__u64__min(((uint64_t)(io2_a_src - iop_a_src)), v_n64))))));
26970 v_token_length = ((uint32_t)((v_n64 & 65535)));
26971 if (v_token_length <= 0) {
26972 if ((a_src && a_src->meta.closed) || (((uint64_t)(io2_a_src - iop_a_src)) >= 4)) {
26973 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
26974 goto exit;
26975 }
26976 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
26977 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
26978 goto label__1__continue;
26979 }
26980 if (((uint64_t)(io2_a_src - iop_a_src)) < ((uint64_t)(v_token_length))) {
26981 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_token_length);
26982 goto exit;
26983 }
26984 v_string_length -= ((uint64_t)(v_token_length));
26985 v_continued = 0;
26986 if ((v_string_length > 0) || (v_indefinite_string_major_type > 0)) {
26987 v_continued = 1;
26988 }
26989 iop_a_src += v_token_length;
26990 *iop_a_dst++ = wuffs_base__make_token(
26991 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
26992 (((uint64_t)(v_continued)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
26993 (((uint64_t)(v_token_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
26994 if (v_string_length > 0) {
26995 goto label__1__continue;
26996 } else if (v_indefinite_string_major_type > 0) {
26997 goto label__outer__continue;
26998 }
26999 goto label__goto_parsed_a_leaf_value__break;
27000 }
27001 } else if (v_c_major == 4) {
27002 if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
27003 goto label__goto_fail__break;
27004 } else if (v_depth >= 1024) {
27005 v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor]));
27006 while ((v_token_length > 0) && (iop_a_src > io1_a_src)) {
27007 iop_a_src--;
27008 v_token_length -= 1;
27009 }
27010 status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
27011 goto exit;
27012 }
27013 v_vminor = 2105361;
27014 v_vminor_alt = 2101282;
27015 if (v_depth > 0) {
27016 v_stack_byte = ((v_depth - 1) / 16);
27017 v_stack_bit = (((v_depth - 1) & 15) * 2);
27018 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
27019 v_vminor = 2105377;
27020 v_vminor_alt = 2105378;
27021 } else {
27022 v_vminor = 2105409;
27023 v_vminor_alt = 2113570;
27024 }
27025 }
27026 *iop_a_dst++ = wuffs_base__make_token(
27027 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27028 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27029 if (v_c_minor == 0) {
27030 *iop_a_dst++ = wuffs_base__make_token(
27031 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27032 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27033 goto label__goto_parsed_a_leaf_value__break;
27034 }
27035 v_stack_byte = (v_depth / 16);
27036 v_stack_bit = ((v_depth & 15) * 2);
27037 self->private_data.f_stack[v_stack_byte] &= (4294967295 ^ (((uint32_t)(3)) << v_stack_bit));
27038 self->private_data.f_container_num_remaining[v_depth] = v_string_length;
27039 v_depth += 1;
27040 v_tagged = false;
27041 goto label__outer__continue;
27042 } else if (v_c_major == 5) {
27043 if (WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor] == 0) {
27044 goto label__goto_fail__break;
27045 } else if (v_depth >= 1024) {
27046 v_token_length = ((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor]));
27047 while ((v_token_length > 0) && (iop_a_src > io1_a_src)) {
27048 iop_a_src--;
27049 v_token_length -= 1;
27050 }
27051 status = wuffs_base__make_status(wuffs_cbor__error__unsupported_recursion_depth);
27052 goto exit;
27053 }
27054 v_vminor = 2113553;
27055 v_vminor_alt = 2101314;
27056 if (v_depth > 0) {
27057 v_stack_byte = ((v_depth - 1) / 16);
27058 v_stack_bit = (((v_depth - 1) & 15) * 2);
27059 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
27060 v_vminor = 2113569;
27061 v_vminor_alt = 2105410;
27062 } else {
27063 v_vminor = 2113601;
27064 v_vminor_alt = 2113602;
27065 }
27066 }
27067 *iop_a_dst++ = wuffs_base__make_token(
27068 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27069 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27070 if (v_c_minor == 0) {
27071 *iop_a_dst++ = wuffs_base__make_token(
27072 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27073 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27074 goto label__goto_parsed_a_leaf_value__break;
27075 }
27076 v_stack_byte = (v_depth / 16);
27077 v_stack_bit = ((v_depth & 15) * 2);
27078 self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(3)) << v_stack_bit);
27079 self->private_data.f_container_num_remaining[v_depth] = v_string_length;
27080 v_depth += 1;
27081 v_tagged = false;
27082 goto label__outer__continue;
27083 } else if (v_c_major == 6) {
27084 if (v_c_minor >= 28) {
27085 goto label__goto_fail__break;
27086 }
27087 if (v_string_length < 262144) {
27088 *iop_a_dst++ = wuffs_base__make_token(
27089 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
27090 (((uint64_t)((4194304 | ((uint32_t)(v_string_length))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27091 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27092 } else {
27093 *iop_a_dst++ = wuffs_base__make_token(
27094 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
27095 (((uint64_t)((4194304 | ((uint32_t)((v_string_length >> 46)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27096 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
27097 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27098 *iop_a_dst++ = wuffs_base__make_token(
27099 (~(v_string_length & 70368744177663) << WUFFS_BASE__TOKEN__VALUE_EXTENSION__SHIFT) |
27100 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27101 }
27102 v_tagged = true;
27103 goto label__outer__continue;
27104 } else if (v_c_major == 7) {
27105 if (v_c_minor < 20) {
27106 *iop_a_dst++ = wuffs_base__make_token(
27107 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
27108 (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27109 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27110 goto label__goto_parsed_a_leaf_value__break;
27111 } else if (v_c_minor < 24) {
27112 *iop_a_dst++ = wuffs_base__make_token(
27113 (((uint64_t)(WUFFS_CBOR__LITERALS[(v_c_minor & 3)])) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27114 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27115 goto label__goto_parsed_a_leaf_value__break;
27116 } else if (v_c_minor == 24) {
27117 if (v_string_length < 24) {
27118 if ( ! (iop_a_src > io1_a_src)) {
27119 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
27120 goto exit;
27121 }
27122 iop_a_src--;
27123 goto label__goto_fail__break;
27124 }
27125 *iop_a_dst++ = wuffs_base__make_token(
27126 (((uint64_t)(787997)) << WUFFS_BASE__TOKEN__VALUE_MAJOR__SHIFT) |
27127 (((uint64_t)((8388608 | ((uint32_t)((v_string_length & 255)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27128 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27129 goto label__goto_parsed_a_leaf_value__break;
27130 } else if (v_c_minor < 28) {
27131 *iop_a_dst++ = wuffs_base__make_token(
27132 (((uint64_t)(10490113)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27133 (((uint64_t)(((uint32_t)(WUFFS_CBOR__TOKEN_LENGTHS[v_c_minor])))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27134 goto label__goto_parsed_a_leaf_value__break;
27135 } else if (v_c_minor == 31) {
27136 if (v_tagged || (v_depth <= 0)) {
27137 goto label__goto_fail__break;
27138 }
27139 v_depth -= 1;
27140 if (self->private_data.f_container_num_remaining[v_depth] != 0) {
27141 goto label__goto_fail__break;
27142 }
27143 v_stack_byte = (v_depth / 16);
27144 v_stack_bit = ((v_depth & 15) * 2);
27145 v_stack_val = (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit));
27146 if (v_stack_val == 1) {
27147 goto label__goto_fail__break;
27148 }
27149 if (v_stack_val != 3) {
27150 v_vminor_alt = 2097186;
27151 } else {
27152 v_vminor_alt = 2097218;
27153 }
27154 if (v_depth <= 0) {
27155 v_vminor_alt |= 4096;
27156 } else {
27157 v_stack_byte = ((v_depth - 1) / 16);
27158 v_stack_bit = (((v_depth - 1) & 15) * 2);
27159 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
27160 v_vminor_alt |= 8192;
27161 } else {
27162 v_vminor_alt |= 16384;
27163 }
27164 }
27165 *iop_a_dst++ = wuffs_base__make_token(
27166 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27167 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27168 goto label__goto_parsed_a_leaf_value__break;
27169 }
27170 }
27171 goto label__goto_fail__break;
27172 }
27173 label__goto_fail__break:;
27174 if (iop_a_src > io1_a_src) {
27175 iop_a_src--;
27176 status = wuffs_base__make_status(wuffs_cbor__error__bad_input);
27177 goto exit;
27178 }
27179 status = wuffs_base__make_status(wuffs_cbor__error__internal_error_inconsistent_i_o);
27180 goto exit;
27181 }
27182 label__goto_parsed_a_leaf_value__break:;
27183 v_tagged = false;
27184 while (v_depth > 0) {
27185 v_stack_byte = ((v_depth - 1) / 16);
27186 v_stack_bit = (((v_depth - 1) & 15) * 2);
27187 self->private_data.f_stack[v_stack_byte] ^= (((uint32_t)(1)) << (v_stack_bit + 1));
27188 if (1 == (3 & (self->private_data.f_stack[v_stack_byte] >> v_stack_bit))) {
27189 goto label__outer__continue;
27190 }
27191 if (self->private_data.f_container_num_remaining[(v_depth - 1)] <= 0) {
27192 goto label__outer__continue;
27193 }
27194 self->private_data.f_container_num_remaining[(v_depth - 1)] -= 1;
27195 if (self->private_data.f_container_num_remaining[(v_depth - 1)] > 0) {
27196 goto label__outer__continue;
27197 }
27198 label__2__continue:;
27199 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
27200 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
27201 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
27202 goto label__2__continue;
27203 }
27204 v_depth -= 1;
27205 v_stack_byte = (v_depth / 16);
27206 v_stack_bit = ((v_depth & 15) * 2);
27207 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
27208 v_vminor_alt = 2097186;
27209 } else {
27210 v_vminor_alt = 2097218;
27211 }
27212 if (v_depth <= 0) {
27213 v_vminor_alt |= 4096;
27214 } else {
27215 v_stack_byte = ((v_depth - 1) / 16);
27216 v_stack_bit = (((v_depth - 1) & 15) * 2);
27217 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
27218 v_vminor_alt |= 8192;
27219 } else {
27220 v_vminor_alt |= 16384;
27221 }
27222 }
27223 *iop_a_dst++ = wuffs_base__make_token(
27224 (((uint64_t)(v_vminor_alt)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
27225 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
27226 }
27227 goto label__outer__break;
27228 }
27229 label__outer__break:;
27230 self->private_impl.f_end_of_data = true;
27231
Nigel Taoe360a532021-04-05 22:47:03 +100027232 ok:
27233 self->private_impl.p_decode_tokens[0] = 0;
27234 goto exit;
27235 }
27236
27237 goto suspend;
27238 suspend:
27239 self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
27240 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
27241 self->private_data.s_decode_tokens[0].v_string_length = v_string_length;
27242 self->private_data.s_decode_tokens[0].v_depth = v_depth;
Nigel Taoe360a532021-04-05 22:47:03 +100027243 self->private_data.s_decode_tokens[0].v_tagged = v_tagged;
27244 self->private_data.s_decode_tokens[0].v_indefinite_string_major_type = v_indefinite_string_major_type;
27245
27246 goto exit;
27247 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110027248 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100027249 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
27250 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110027251 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100027252 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
27253 }
27254
27255 if (wuffs_base__status__is_error(&status)) {
27256 self->private_impl.magic = WUFFS_BASE__DISABLED;
27257 }
27258 return status;
27259}
27260
27261#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CBOR)
27262
27263#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32)
27264
27265// ---------------- Status Codes Implementations
27266
27267// ---------------- Private Consts
27268
27269static const uint32_t
27270WUFFS_CRC32__IEEE_TABLE[16][256] WUFFS_BASE__POTENTIALLY_UNUSED = {
27271 {
27272 0, 1996959894, 3993919788, 2567524794, 124634137, 1886057615, 3915621685, 2657392035,
27273 249268274, 2044508324, 3772115230, 2547177864, 162941995, 2125561021, 3887607047, 2428444049,
27274 498536548, 1789927666, 4089016648, 2227061214, 450548861, 1843258603, 4107580753, 2211677639,
27275 325883990, 1684777152, 4251122042, 2321926636, 335633487, 1661365465, 4195302755, 2366115317,
27276 997073096, 1281953886, 3579855332, 2724688242, 1006888145, 1258607687, 3524101629, 2768942443,
27277 901097722, 1119000684, 3686517206, 2898065728, 853044451, 1172266101, 3705015759, 2882616665,
27278 651767980, 1373503546, 3369554304, 3218104598, 565507253, 1454621731, 3485111705, 3099436303,
27279 671266974, 1594198024, 3322730930, 2970347812, 795835527, 1483230225, 3244367275, 3060149565,
27280 1994146192, 31158534, 2563907772, 4023717930, 1907459465, 112637215, 2680153253, 3904427059,
27281 2013776290, 251722036, 2517215374, 3775830040, 2137656763, 141376813, 2439277719, 3865271297,
27282 1802195444, 476864866, 2238001368, 4066508878, 1812370925, 453092731, 2181625025, 4111451223,
27283 1706088902, 314042704, 2344532202, 4240017532, 1658658271, 366619977, 2362670323, 4224994405,
27284 1303535960, 984961486, 2747007092, 3569037538, 1256170817, 1037604311, 2765210733, 3554079995,
27285 1131014506, 879679996, 2909243462, 3663771856, 1141124467, 855842277, 2852801631, 3708648649,
27286 1342533948, 654459306, 3188396048, 3373015174, 1466479909, 544179635, 3110523913, 3462522015,
27287 1591671054, 702138776, 2966460450, 3352799412, 1504918807, 783551873, 3082640443, 3233442989,
27288 3988292384, 2596254646, 62317068, 1957810842, 3939845945, 2647816111, 81470997, 1943803523,
27289 3814918930, 2489596804, 225274430, 2053790376, 3826175755, 2466906013, 167816743, 2097651377,
27290 4027552580, 2265490386, 503444072, 1762050814, 4150417245, 2154129355, 426522225, 1852507879,
27291 4275313526, 2312317920, 282753626, 1742555852, 4189708143, 2394877945, 397917763, 1622183637,
27292 3604390888, 2714866558, 953729732, 1340076626, 3518719985, 2797360999, 1068828381, 1219638859,
27293 3624741850, 2936675148, 906185462, 1090812512, 3747672003, 2825379669, 829329135, 1181335161,
27294 3412177804, 3160834842, 628085408, 1382605366, 3423369109, 3138078467, 570562233, 1426400815,
27295 3317316542, 2998733608, 733239954, 1555261956, 3268935591, 3050360625, 752459403, 1541320221,
27296 2607071920, 3965973030, 1969922972, 40735498, 2617837225, 3943577151, 1913087877, 83908371,
27297 2512341634, 3803740692, 2075208622, 213261112, 2463272603, 3855990285, 2094854071, 198958881,
27298 2262029012, 4057260610, 1759359992, 534414190, 2176718541, 4139329115, 1873836001, 414664567,
27299 2282248934, 4279200368, 1711684554, 285281116, 2405801727, 4167216745, 1634467795, 376229701,
27300 2685067896, 3608007406, 1308918612, 956543938, 2808555105, 3495958263, 1231636301, 1047427035,
27301 2932959818, 3654703836, 1088359270, 936918000, 2847714899, 3736837829, 1202900863, 817233897,
27302 3183342108, 3401237130, 1404277552, 615818150, 3134207493, 3453421203, 1423857449, 601450431,
27303 3009837614, 3294710456, 1567103746, 711928724, 3020668471, 3272380065, 1510334235, 755167117,
27304 }, {
27305 0, 421212481, 842424962, 724390851, 1684849924, 2105013317, 1448781702, 1329698503,
27306 3369699848, 3519200073, 4210026634, 3824474571, 2897563404, 3048111693, 2659397006, 2274893007,
27307 1254232657, 1406739216, 2029285587, 1643069842, 783210325, 934667796, 479770071, 92505238,
27308 2182846553, 2600511768, 2955803355, 2838940570, 3866582365, 4285295644, 3561045983, 3445231262,
27309 2508465314, 2359236067, 2813478432, 3198777185, 4058571174, 3908292839, 3286139684, 3670389349,
27310 1566420650, 1145479147, 1869335592, 1987116393, 959540142, 539646703, 185010476, 303839341,
27311 3745920755, 3327985586, 3983561841, 4100678960, 3140154359, 2721170102, 2300350837, 2416418868,
27312 396344571, 243568058, 631889529, 1018359608, 1945336319, 1793607870, 1103436669, 1490954812,
27313 4034481925, 3915546180, 3259968903, 3679722694, 2484439553, 2366552896, 2787371139, 3208174018,
27314 950060301, 565965900, 177645455, 328046286, 1556873225, 1171730760, 1861902987, 2011255754,
27315 3132841300, 2745199637, 2290958294, 2442530455, 3738671184, 3352078609, 3974232786, 4126854035,
27316 1919080284, 1803150877, 1079293406, 1498383519, 370020952, 253043481, 607678682, 1025720731,
27317 1711106983, 2095471334, 1472923941, 1322268772, 26324643, 411738082, 866634785, 717028704,
27318 2904875439, 3024081134, 2668790573, 2248782444, 3376948395, 3495106026, 4219356713, 3798300520,
27319 792689142, 908347575, 487136116, 68299317, 1263779058, 1380486579, 2036719216, 1618931505,
27320 3890672638, 4278043327, 3587215740, 3435896893, 2206873338, 2593195963, 2981909624, 2829542713,
27321 998479947, 580430090, 162921161, 279890824, 1609522511, 1190423566, 1842954189, 1958874764,
27322 4082766403, 3930137346, 3245109441, 3631694208, 2536953671, 2385372678, 2768287173, 3155920004,
27323 1900120602, 1750776667, 1131931800, 1517083097, 355290910, 204897887, 656092572, 1040194781,
27324 3113746450, 2692952403, 2343461520, 2461357009, 3723805974, 3304059991, 4022511508, 4141455061,
27325 2919742697, 3072101800, 2620513899, 2234183466, 3396041197, 3547351212, 4166851439, 3779471918,
27326 1725839073, 2143618976, 1424512099, 1307796770, 45282277, 464110244, 813994343, 698327078,
27327 3838160568, 4259225593, 3606301754, 3488152955, 2158586812, 2578602749, 2996767038, 2877569151,
27328 740041904, 889656817, 506086962, 120682355, 1215357364, 1366020341, 2051441462, 1667084919,
27329 3422213966, 3538019855, 4190942668, 3772220557, 2945847882, 3062702859, 2644537544, 2226864521,
27330 52649286, 439905287, 823476164, 672009861, 1733269570, 2119477507, 1434057408, 1281543041,
27331 2167981343, 2552493150, 3004082077, 2853541596, 3847487515, 4233048410, 3613549209, 3464057816,
27332 1239502615, 1358593622, 2077699477, 1657543892, 764250643, 882293586, 532408465, 111204816,
27333 1585378284, 1197851309, 1816695150, 1968414767, 974272232, 587794345, 136598634, 289367339,
27334 2527558116, 2411481253, 2760973158, 3179948583, 4073438432, 3956313505, 3237863010, 3655790371,
27335 347922877, 229101820, 646611775, 1066513022, 1892689081, 1774917112, 1122387515, 1543337850,
27336 3697634229, 3313392372, 3998419255, 4148705398, 3087642289, 2702352368, 2319436851, 2468674930,
27337 }, {
27338 0, 29518391, 59036782, 38190681, 118073564, 114017003, 76381362, 89069189,
27339 236147128, 265370511, 228034006, 206958561, 152762724, 148411219, 178138378, 190596925,
27340 472294256, 501532999, 530741022, 509615401, 456068012, 451764635, 413917122, 426358261,
27341 305525448, 334993663, 296822438, 275991697, 356276756, 352202787, 381193850, 393929805,
27342 944588512, 965684439, 1003065998, 973863097, 1061482044, 1049003019, 1019230802, 1023561829,
27343 912136024, 933002607, 903529270, 874031361, 827834244, 815125939, 852716522, 856752605,
27344 611050896, 631869351, 669987326, 640506825, 593644876, 580921211, 551983394, 556069653,
27345 712553512, 733666847, 704405574, 675154545, 762387700, 749958851, 787859610, 792175277,
27346 1889177024, 1901651959, 1931368878, 1927033753, 2006131996, 1985040171, 1947726194, 1976933189,
27347 2122964088, 2135668303, 2098006038, 2093965857, 2038461604, 2017599123, 2047123658, 2076625661,
27348 1824272048, 1836991623, 1866005214, 1861914857, 1807058540, 1786244187, 1748062722, 1777547317,
27349 1655668488, 1668093247, 1630251878, 1625932113, 1705433044, 1684323811, 1713505210, 1742760333,
27350 1222101792, 1226154263, 1263738702, 1251046777, 1339974652, 1310460363, 1281013650, 1301863845,
27351 1187289752, 1191637167, 1161842422, 1149379777, 1103966788, 1074747507, 1112139306, 1133218845,
27352 1425107024, 1429406311, 1467333694, 1454888457, 1408811148, 1379576507, 1350309090, 1371438805,
27353 1524775400, 1528845279, 1499917702, 1487177649, 1575719220, 1546255107, 1584350554, 1605185389,
27354 3778354048, 3774312887, 3803303918, 3816007129, 3862737756, 3892238699, 3854067506, 3833203973,
27355 4012263992, 4007927823, 3970080342, 3982554209, 3895452388, 3924658387, 3953866378, 3932773565,
27356 4245928176, 4241609415, 4271336606, 4283762345, 4196012076, 4225268251, 4187931714, 4166823541,
27357 4076923208, 4072833919, 4035198246, 4047918865, 4094247316, 4123732899, 4153251322, 4132437965,
27358 3648544096, 3636082519, 3673983246, 3678331705, 3732010428, 3753090955, 3723829714, 3694611429,
27359 3614117080, 3601426159, 3572488374, 3576541825, 3496125444, 3516976691, 3555094634, 3525581405,
27360 3311336976, 3298595879, 3336186494, 3340255305, 3260503756, 3281337595, 3251864226, 3222399125,
27361 3410866088, 3398419871, 3368647622, 3372945905, 3427010420, 3448139075, 3485520666, 3456284973,
27362 2444203584, 2423127159, 2452308526, 2481530905, 2527477404, 2539934891, 2502093554, 2497740997,
27363 2679949304, 2659102159, 2620920726, 2650438049, 2562027300, 2574714131, 2603727690, 2599670141,
27364 2374579504, 2353749767, 2383274334, 2412743529, 2323684844, 2336421851, 2298759554, 2294686645,
27365 2207933576, 2186809023, 2149495014, 2178734801, 2224278612, 2236720739, 2266437690, 2262135309,
27366 2850214048, 2820717207, 2858812622, 2879680249, 2934667388, 2938704459, 2909776914, 2897069605,
27367 2817622296, 2788420399, 2759153014, 2780249921, 2700618180, 2704950259, 2742877610, 2730399645,
27368 3049550800, 3020298727, 3057690558, 3078802825, 2999835404, 3004150075, 2974355298, 2961925461,
27369 3151438440, 3121956959, 3092510214, 3113327665, 3168701108, 3172786307, 3210370778, 3197646061,
27370 }, {
27371 0, 3099354981, 2852767883, 313896942, 2405603159, 937357362, 627793884, 2648127673,
27372 3316918511, 2097696650, 1874714724, 3607201537, 1255587768, 4067088605, 3772741427, 1482887254,
27373 1343838111, 3903140090, 4195393300, 1118632049, 3749429448, 1741137837, 1970407491, 3452858150,
27374 2511175536, 756094997, 1067759611, 2266550430, 449832999, 2725482306, 2965774508, 142231497,
27375 2687676222, 412010587, 171665333, 2995192016, 793786473, 2548850444, 2237264098, 1038456711,
27376 1703315409, 3711623348, 3482275674, 1999841343, 3940814982, 1381529571, 1089329165, 4166106984,
27377 4029413537, 1217896388, 1512189994, 3802027855, 2135519222, 3354724499, 3577784189, 1845280792,
27378 899665998, 2367928107, 2677414085, 657096608, 3137160985, 37822588, 284462994, 2823350519,
27379 2601801789, 598228824, 824021174, 2309093331, 343330666, 2898962447, 3195996129, 113467524,
27380 1587572946, 3860600759, 4104763481, 1276501820, 3519211397, 1769898208, 2076913422, 3279374443,
27381 3406630818, 1941006535, 1627703081, 3652755532, 1148164341, 4241751952, 3999682686, 1457141531,
27382 247015245, 3053797416, 2763059142, 470583459, 2178658330, 963106687, 735213713, 2473467892,
27383 992409347, 2207944806, 2435792776, 697522413, 3024379988, 217581361, 508405983, 2800865210,
27384 4271038444, 1177467017, 1419450215, 3962007554, 1911572667, 3377213406, 3690561584, 1665525589,
27385 1799331996, 3548628985, 3241568279, 2039091058, 3831314379, 1558270126, 1314193216, 4142438437,
27386 2928380019, 372764438, 75645176, 3158189981, 568925988, 2572515393, 2346768303, 861712586,
27387 3982079547, 1441124702, 1196457648, 4293663189, 1648042348, 3666298377, 3358779879, 1888390786,
27388 686661332, 2421291441, 2196002399, 978858298, 2811169155, 523464422, 226935048, 3040519789,
27389 3175145892, 100435649, 390670639, 2952089162, 841119475, 2325614998, 2553003640, 546822429,
27390 2029308235, 3225988654, 3539796416, 1782671013, 4153826844, 1328167289, 1570739863, 3844338162,
27391 1298864389, 4124540512, 3882013070, 1608431339, 3255406162, 2058742071, 1744848601, 3501990332,
27392 2296328682, 811816591, 584513889, 2590678532, 129869501, 3204563416, 2914283062, 352848211,
27393 494030490, 2781751807, 3078325777, 264757620, 2450577869, 715964072, 941166918, 2158327331,
27394 3636881013, 1618608400, 1926213374, 3396585883, 1470427426, 4011365959, 4255988137, 1158766284,
27395 1984818694, 3471935843, 3695453837, 1693991400, 4180638033, 1100160564, 1395044826, 3952793279,
27396 3019491049, 189112716, 435162722, 2706139399, 1016811966, 2217162459, 2526189877, 774831696,
27397 643086745, 2666061564, 2354934034, 887166583, 2838900430, 294275499, 54519365, 3145957664,
27398 3823145334, 1532818963, 1240029693, 4048895640, 1820460577, 3560857924, 3331051178, 2117577167,
27399 3598663992, 1858283101, 2088143283, 3301633750, 1495127663, 3785470218, 4078182116, 1269332353,
27400 332098007, 2876706482, 3116540252, 25085497, 2628386432, 605395429, 916469259, 2384220526,
27401 2254837415, 1054503362, 745528876, 2496903497, 151290352, 2981684885, 2735556987, 464596510,
27402 1137851976, 4218313005, 3923506883, 1365741990, 3434129695, 1946996346, 1723425172, 3724871409,
27403 }, {
27404 0, 1029712304, 2059424608, 1201699536, 4118849216, 3370159984, 2403399072, 2988497936,
27405 812665793, 219177585, 1253054625, 2010132753, 3320900865, 4170237105, 3207642721, 2186319825,
27406 1625331586, 1568718386, 438355170, 658566482, 2506109250, 2818578674, 4020265506, 3535817618,
27407 1351670851, 1844508147, 709922595, 389064339, 2769320579, 2557498163, 3754961379, 3803185235,
27408 3250663172, 4238411444, 3137436772, 2254525908, 876710340, 153198708, 1317132964, 1944187668,
27409 4054934725, 3436268917, 2339452837, 3054575125, 70369797, 961670069, 2129760613, 1133623509,
27410 2703341702, 2621542710, 3689016294, 3867263574, 1419845190, 1774270454, 778128678, 318858390,
27411 2438067015, 2888948471, 3952189479, 3606153623, 1691440519, 1504803895, 504432359, 594620247,
27412 1492342857, 1704161785, 573770537, 525542041, 2910060169, 2417219385, 3618876905, 3939730521,
27413 1753420680, 1440954936, 306397416, 790849880, 2634265928, 2690882808, 3888375336, 3668168600,
27414 940822475, 91481723, 1121164459, 2142483739, 3448989963, 4042473659, 3075684971, 2318603227,
27415 140739594, 889433530, 1923340138, 1338244826, 4259521226, 3229813626, 2267247018, 3124975642,
27416 2570221389, 2756861693, 3824297005, 3734113693, 1823658381, 1372780605, 376603373, 722643805,
27417 2839690380, 2485261628, 3548540908, 4007806556, 1556257356, 1638052860, 637716780, 459464860,
27418 4191346895, 3300051327, 2199040943, 3195181599, 206718479, 825388991, 1989285231, 1274166495,
27419 3382881038, 4106388158, 3009607790, 2382549470, 1008864718, 21111934, 1189240494, 2072147742,
27420 2984685714, 2357631266, 3408323570, 4131834434, 1147541074, 2030452706, 1051084082, 63335554,
27421 2174155603, 3170292451, 4216760371, 3325460867, 1947622803, 1232499747, 248909555, 867575619,
27422 3506841360, 3966111392, 2881909872, 2527485376, 612794832, 434546784, 1581699760, 1663499008,
27423 3782634705, 3692447073, 2612412337, 2799048193, 351717905, 697754529, 1849071985, 1398190273,
27424 1881644950, 1296545318, 182963446, 931652934, 2242328918, 3100053734, 4284967478, 3255255942,
27425 1079497815, 2100821479, 983009079, 133672583, 3050795671, 2293717799, 3474399735, 4067887175,
27426 281479188, 765927844, 1778867060, 1466397380, 3846680276, 3626469220, 2676489652, 2733102084,
27427 548881365, 500656741, 1517752501, 1729575173, 3577210133, 3898068133, 2952246901, 2459410373,
27428 3910527195, 3564487019, 2480257979, 2931134987, 479546907, 569730987, 1716854139, 1530213579,
27429 3647316762, 3825568426, 2745561210, 2663766474, 753206746, 293940330, 1445287610, 1799716618,
27430 2314567513, 3029685993, 4080348217, 3461678473, 2088098201, 1091956777, 112560889, 1003856713,
27431 3112514712, 2229607720, 3276105720, 4263857736, 1275433560, 1902492648, 918929720, 195422344,
27432 685033439, 364179055, 1377080511, 1869921551, 3713294623, 3761522863, 2811507327, 2599689167,
27433 413436958, 633644462, 1650777982, 1594160846, 3978570462, 3494118254, 2548332990, 2860797966,
27434 1211387997, 1968470509, 854852413, 261368461, 3182753437, 2161434413, 3346310653, 4195650637,
27435 2017729436, 1160000044, 42223868, 1071931724, 2378480988, 2963576044, 4144295484, 3395602316,
27436 }, {
27437 0, 3411858341, 1304994059, 2257875630, 2609988118, 1355649459, 3596215069, 486879416,
27438 3964895853, 655315400, 2711298918, 1791488195, 2009251963, 3164476382, 973758832, 4048990933,
27439 64357019, 3364540734, 1310630800, 2235723829, 2554806413, 1394316072, 3582976390, 517157411,
27440 4018503926, 618222419, 2722963965, 1762783832, 1947517664, 3209171269, 970744811, 4068520014,
27441 128714038, 3438335635, 1248109629, 2167961496, 2621261600, 1466012805, 3522553387, 447296910,
27442 3959392091, 547575038, 2788632144, 1835791861, 1886307661, 3140622056, 1034314822, 4143626211,
27443 75106221, 3475428360, 1236444838, 2196665603, 2682996155, 1421317662, 3525567664, 427767573,
27444 3895035328, 594892389, 2782995659, 1857943406, 1941489622, 3101955187, 1047553757, 4113347960,
27445 257428076, 3288652233, 1116777319, 2311878850, 2496219258, 1603640287, 3640781169, 308099796,
27446 3809183745, 676813732, 2932025610, 1704983215, 2023410199, 3016104370, 894593820, 4262377657,
27447 210634999, 3352484690, 1095150076, 2316991065, 2535410401, 1547934020, 3671583722, 294336591,
27448 3772615322, 729897279, 2903845777, 1716123700, 2068629644, 2953845545, 914647431, 4258839074,
27449 150212442, 3282623743, 1161604689, 2388688372, 2472889676, 1480171241, 3735940167, 368132066,
27450 3836185911, 805002898, 2842635324, 1647574937, 2134298401, 3026852996, 855535146, 4188192143,
27451 186781121, 3229539940, 1189784778, 2377547631, 2427670487, 1542429810, 3715886812, 371670393,
27452 3882979244, 741170185, 2864262823, 1642462466, 2095107514, 3082559007, 824732849, 4201955092,
27453 514856152, 3589064573, 1400419795, 2552522358, 2233554638, 1316849003, 3370776517, 62202976,
27454 4075001525, 968836368, 3207280574, 1954014235, 1769133219, 2720925446, 616199592, 4024870413,
27455 493229635, 3594175974, 1353627464, 2616354029, 2264355925, 1303087088, 3409966430, 6498043,
27456 4046820398, 979978123, 3170710821, 2007099008, 1789187640, 2717386141, 661419827, 3962610838,
27457 421269998, 3527459403, 1423225061, 2676515648, 2190300152, 1238466653, 3477467891, 68755798,
27458 4115633027, 1041448998, 3095868040, 1943789869, 1860096405, 2776760880, 588673182, 3897205563,
27459 449450869, 3516317904, 1459794558, 2623431131, 2170245475, 1242006214, 3432247400, 131015629,
27460 4137259288, 1036337853, 3142660115, 1879958454, 1829294862, 2790523051, 549483013, 3952910752,
27461 300424884, 3669282065, 1545650111, 2541513754, 2323209378, 1092980487, 3350330793, 216870412,
27462 4256931033, 921128828, 2960342482, 2066738807, 1714085583, 2910195050, 736264132, 3770592353,
27463 306060335, 3647131530, 1610005796, 2494197377, 2309971513, 1123257756, 3295149874, 255536279,
27464 4268596802, 892423655, 3013951305, 2029645036, 1711070292, 2929725425, 674528607, 3815288570,
27465 373562242, 3709388839, 1535949449, 2429577516, 2379569556, 1183418929, 3223189663, 188820282,
27466 4195850735, 827017802, 3084859620, 2089020225, 1636228089, 2866415708, 743340786, 3876759895,
27467 361896217, 3738094268, 1482340370, 2466671543, 2382584591, 1163888810, 3284924932, 144124321,
27468 4190215028, 849168593, 3020503679, 2136336858, 1649465698, 2836138695, 798521449, 3838094284,
27469 }, {
27470 0, 2792819636, 2543784233, 837294749, 4098827283, 1379413927, 1674589498, 3316072078,
27471 871321191, 2509784531, 2758827854, 34034938, 3349178996, 1641505216, 1346337629, 4131942633,
27472 1742642382, 3249117050, 4030828007, 1446413907, 2475800797, 904311657, 68069876, 2725880384,
27473 1412551337, 4064729373, 3283010432, 1708771380, 2692675258, 101317902, 937551763, 2442587175,
27474 3485284764, 1774858792, 1478633653, 4266992385, 1005723023, 2642744891, 2892827814, 169477906,
27475 4233263099, 1512406095, 1808623314, 3451546982, 136139752, 2926205020, 2676114113, 972376437,
27476 2825102674, 236236518, 1073525883, 2576072655, 1546420545, 4200303349, 3417542760, 1841601500,
27477 2609703733, 1039917185, 202635804, 2858742184, 1875103526, 3384067218, 4166835727, 1579931067,
27478 1141601657, 3799809741, 3549717584, 1977839588, 2957267306, 372464350, 668680259, 2175552503,
27479 2011446046, 3516084394, 3766168119, 1175200131, 2209029901, 635180217, 338955812, 2990736784,
27480 601221559, 2242044419, 3024812190, 306049834, 3617246628, 1911408144, 1074125965, 3866285881,
27481 272279504, 3058543716, 2275784441, 567459149, 3832906691, 1107462263, 1944752874, 3583875422,
27482 2343980261, 767641425, 472473036, 3126744696, 2147051766, 3649987394, 3899029983, 1309766251,
27483 3092841090, 506333494, 801510315, 2310084639, 1276520081, 3932237093, 3683203000, 2113813516,
27484 3966292011, 1243601823, 2079834370, 3716205238, 405271608, 3192979340, 2411259153, 701492901,
27485 3750207052, 2045810168, 1209569125, 4000285905, 734575199, 2378150379, 3159862134, 438345922,
27486 2283203314, 778166598, 529136603, 3120492655, 2086260449, 3660498261, 3955679176, 1303499900,
27487 3153699989, 495890209, 744928700, 2316418568, 1337360518, 3921775410, 3626602927, 2120129051,
27488 4022892092, 1237286280, 2018993941, 3726666913, 461853231, 3186645403, 2350400262, 711936178,
27489 3693557851, 2052076527, 1270360434, 3989775046, 677911624, 2384402428, 3220639073, 427820757,
27490 1202443118, 3789347034, 3493118535, 1984154099, 3018127229, 362020041, 612099668, 2181885408,
27491 1950653705, 3526596285, 3822816288, 1168934804, 2148251930, 645706414, 395618355, 2984485767,
27492 544559008, 2248295444, 3085590153, 295523645, 3560598451, 1917673479, 1134918298, 3855773998,
27493 328860103, 3052210803, 2214924526, 577903450, 3889505748, 1101147744, 1883911421, 3594338121,
27494 3424493451, 1785369663, 1535282850, 4260726038, 944946072, 2653270060, 2949491377, 163225861,
27495 4294103532, 1501944408, 1752023237, 3457862513, 196998655, 2915761739, 2619532502, 978710370,
27496 2881684293, 229902577, 1012666988, 2586515928, 1603020630, 4193987810, 3356702335, 1852063179,
27497 2553040162, 1046169238, 263412747, 2848217023, 1818454321, 3390333573, 4227627032, 1569420204,
27498 60859927, 2782375331, 2487203646, 843627658, 4159668740, 1368951216, 1617990445, 3322386585,
27499 810543216, 2520310724, 2815490393, 27783917, 3288386659, 1652017111, 1402985802, 4125677310,
27500 1685994201, 3255382381, 4091620336, 1435902020, 2419138250, 910562686, 128847843, 2715354199,
27501 1469150398, 4058414858, 3222168983, 1719234083, 2749255853, 94984985, 876691844, 2453031472,
27502 }, {
27503 0, 3433693342, 1109723005, 2391738339, 2219446010, 1222643300, 3329165703, 180685081,
27504 3555007413, 525277995, 2445286600, 1567235158, 1471092047, 2600801745, 361370162, 3642757804,
27505 2092642603, 2953916853, 1050555990, 4063508168, 4176560081, 878395215, 3134470316, 1987983410,
27506 2942184094, 1676945920, 3984272867, 567356797, 722740324, 3887998202, 1764827929, 2778407815,
27507 4185285206, 903635656, 3142804779, 2012833205, 2101111980, 2979425330, 1058630609, 4088621903,
27508 714308067, 3862526333, 1756790430, 2753330688, 2933487385, 1651734407, 3975966820, 542535930,
27509 2244825981, 1231508451, 3353891840, 188896414, 25648519, 3442302233, 1134713594, 2399689316,
27510 1445480648, 2592229462, 336416693, 3634843435, 3529655858, 516441772, 2420588879, 1559052753,
27511 698204909, 3845636723, 1807271312, 2803025166, 2916600855, 1635634313, 4025666410, 593021940,
27512 4202223960, 919787974, 3093159461, 1962401467, 2117261218, 2996361020, 1008193759, 4038971457,
27513 1428616134, 2576151384, 386135227, 3685348389, 3513580860, 499580322, 2471098945, 1608776415,
27514 2260985971, 1248454893, 3303468814, 139259792, 42591881, 3458459159, 1085071860, 2349261162,
27515 3505103035, 474062885, 2463016902, 1583654744, 1419882049, 2550902495, 377792828, 3660491170,
27516 51297038, 3483679632, 1093385331, 2374089965, 2269427188, 1273935210, 3311514249, 164344343,
27517 2890961296, 1627033870, 4000683757, 585078387, 672833386, 3836780532, 1782552599, 2794821769,
27518 2142603813, 3005188795, 1032883544, 4047146438, 4227826911, 928351297, 3118105506, 1970307900,
27519 1396409818, 2677114180, 287212199, 3719594553, 3614542624, 467372990, 2505346141, 1509854403,
27520 2162073199, 1282711281, 3271268626, 240228748, 76845205, 3359543307, 1186043880, 2317064054,
27521 796964081, 3811226735, 1839575948, 2702160658, 2882189835, 1734392469, 3924802934, 625327592,
27522 4234522436, 818917338, 3191908409, 1927981223, 2016387518, 3028656416, 973776579, 4137723485,
27523 2857232268, 1726474002, 3899187441, 616751215, 772270454, 3803048424, 1814228491, 2693328533,
27524 2041117753, 3036871847, 999160644, 4146592730, 4259508931, 826864221, 3217552830, 1936586016,
27525 3606501031, 442291769, 2496909786, 1484378436, 1388107869, 2652297411, 278519584, 3694387134,
27526 85183762, 3384397196, 1194773103, 2342308593, 2170143720, 1307820918, 3279733909, 265733131,
27527 2057717559, 3054258089, 948125770, 4096344276, 4276898253, 843467091, 3167309488, 1885556270,
27528 2839764098, 1709792284, 3949353983, 667704161, 755585656, 3785577190, 1865176325, 2743489947,
27529 102594076, 3401021058, 1144549729, 2291298815, 2186770662, 1325234296, 3228729243, 215514885,
27530 3589828009, 424832311, 2547870420, 1534552650, 1370645331, 2635621325, 328688686, 3745342640,
27531 2211456353, 1333405183, 3254067740, 224338562, 127544219, 3408931589, 1170156774, 2299866232,
27532 1345666772, 2627681866, 303053225, 3736746295, 3565105198, 416624816, 2522494803, 1525692365,
27533 4285207626, 868291796, 3176010551, 1910772649, 2065767088, 3079346734, 956571085, 4121828691,
27534 747507711, 3760459617, 1856702594, 2717976604, 2831417605, 1684930971, 3940615800, 642451174,
27535 },
27536 {
27537 0, 393942083, 787884166, 965557445, 1575768332, 1251427663, 1931114890, 1684106697,
27538 3151536664, 2896410203, 2502855326, 2186649309, 3862229780, 4048545623, 3368213394, 3753496529,
27539 2898281073, 3149616690, 2184604407, 2504883892, 4046197629, 3864463166, 3755621371, 3366006712,
27540 387506281, 6550570, 971950319, 781573292, 1257550181, 1569695014, 1677892067, 1937345952,
27541 2196865699, 2508887776, 2886183461, 3145514598, 3743273903, 3362179052, 4058774313, 3868258154,
27542 958996667, 777139448, 400492605, 10755198, 1690661303, 1941857780, 1244879153, 1565019506,
27543 775012562, 961205393, 13101140, 398261271, 1943900638, 1688634781, 1563146584, 1246801179,
27544 2515100362, 2190636681, 3139390028, 2892258831, 3355784134, 3749586821, 3874691904, 4052225795,
27545 3734110983, 3387496260, 4033096577, 3877584834, 2206093835, 2483373640, 2911402637, 3136515790,
27546 1699389727, 1915860316, 1270647193, 1556585946, 950464531, 803071056, 374397077, 19647702,
27547 1917993334, 1697207605, 1554278896, 1272937907, 800985210, 952435769, 21510396, 372452543,
27548 3381322606, 3740399405, 3883715560, 4027047851, 2489758306, 2199758369, 3130039012, 2917895847,
27549 1550025124, 1259902439, 1922410786, 1710144865, 26202280, 385139947, 796522542, 939715693,
27550 3887801276, 4039129087, 3377269562, 3728088953, 3126293168, 2905368307, 2493602358, 2212122229,
27551 4037264341, 3889747862, 3730172755, 3375300368, 2907673305, 3124004506, 2209987167, 2495786524,
27552 1266377165, 1543533966, 1703758155, 1928748296, 379007169, 32253058, 945887303, 790236164,
27553 1716846671, 1898845196, 1218652361, 1608006794, 1002000707, 750929152, 357530053, 36990342,
27554 3717046871, 3405166100, 4084959953, 3825245842, 2153902939, 2535122712, 2929187805, 3119304606,
27555 3398779454, 3723384445, 3831720632, 4078468859, 2541294386, 2147616625, 3113171892, 2935238647,
27556 1900929062, 1714877541, 1606142112, 1220599011, 748794154, 1004184937, 39295404, 355241455,
27557 3835986668, 4091516591, 3394415210, 3710500393, 3108557792, 2922629027, 2545875814, 2160455461,
27558 1601970420, 1208431799, 1904871538, 1727077425, 43020792, 367748539, 744905086, 991776061,
27559 1214562461, 1595921630, 1720903707, 1911159896, 361271697, 49513938, 998160663, 738569556,
27560 4089209477, 3838277318, 3712633347, 3392233024, 2924491657, 3106613194, 2158369551, 2547846988,
27561 3100050248, 2948339467, 2519804878, 2169126797, 3844821572, 4065347079, 3420289730, 3701894785,
27562 52404560, 342144275, 770279894, 982687125, 1593045084, 1233708063, 1879431386, 1736363161,
27563 336019769, 58479994, 988899775, 764050940, 1240141877, 1586496630, 1729968307, 1885744368,
27564 2950685473, 3097818978, 2166999975, 2522013668, 4063474221, 3846743662, 3703937707, 3418263272,
27565 976650731, 760059304, 348170605, 62635310, 1742393575, 1889649828, 1227683937, 1582820386,
27566 2179867635, 2526361520, 2937588597, 3093503798, 3691148031, 3413731004, 4076100217, 3851374138,
27567 2532754330, 2173556697, 3087067932, 2944139103, 3407516310, 3697379029, 3857496592, 4070026835,
27568 758014338, 978679233, 64506116, 346250567, 1891774606, 1740186829, 1580472328, 1229917259,
27569 }, {
27570 0, 4022496062, 83218493, 3946298115, 166436986, 3861498692, 220098631, 3806075769,
27571 332873972, 4229245898, 388141257, 4175494135, 440197262, 4127099824, 516501683, 4044053389,
27572 665747944, 3362581206, 593187285, 3432594155, 776282514, 3246869164, 716239279, 3312622225,
27573 880394524, 3686509090, 814485793, 3746462239, 1033003366, 3528460888, 963096923, 3601193573,
27574 1331495888, 2694801646, 1269355501, 2758457555, 1186374570, 2843003028, 1111716759, 2910918825,
27575 1552565028, 3007850522, 1484755737, 3082680359, 1432478558, 3131279456, 1368666979, 3193329757,
27576 1760789048, 2268195078, 1812353541, 2210675003, 1628971586, 2396670332, 1710092927, 2318375233,
27577 2066006732, 2498144754, 2144408305, 2417195471, 1926193846, 2634877320, 1983558283, 2583222709,
27578 2662991776, 1903717534, 2588923805, 1972223139, 2538711002, 2022952164, 2477029351, 2087066841,
27579 2372749140, 1655647338, 2308478825, 1717238871, 2223433518, 1799654416, 2155034387, 1873894445,
27580 3105130056, 1456926070, 3185661557, 1378041163, 2969511474, 1597852940, 3020617231, 1539874097,
27581 2864957116, 1157737858, 2922780289, 1106542015, 2737333958, 1290407416, 2816325371, 1210047941,
27582 3521578096, 1042640718, 3574781005, 986759027, 3624707082, 936300340, 3707335735, 859512585,
27583 3257943172, 770846650, 3334837433, 688390023, 3420185854, 605654976, 3475911875, 552361981,
27584 4132013464, 428600998, 4072428965, 494812827, 4288816610, 274747100, 4216845791, 345349857,
27585 3852387692, 173846098, 3781891409, 245988975, 3967116566, 62328360, 3900749099, 121822741,
27586 3859089665, 164061759, 3807435068, 221426178, 4025395579, 2933317, 3944446278, 81334904,
27587 4124199413, 437265099, 4045904328, 518386422, 4231653775, 335250097, 4174133682, 386814604,
27588 3249244393, 778691543, 3311294676, 714879978, 3359647891, 662848429, 3434477742, 595039120,
27589 3531393053, 1035903779, 3599308832, 961245982, 3684132967, 877986649, 3747788890, 815846244,
27590 2841119441, 1184522735, 2913852140, 1114616274, 2696129195, 1332855189, 2756082326, 1266946472,
27591 3129952805, 1431118107, 3195705880, 1371074854, 3009735263, 1554415969, 3079748194, 1481855324,
27592 2398522169, 1630855175, 2315475716, 1707159610, 2266835779, 1759461501, 2213084030, 1814728768,
27593 2636237773, 1927520499, 2580814832, 1981182158, 2496293815, 2064121993, 2420095882, 2147340468,
27594 2025787041, 2541577631, 2085281436, 2475210146, 1901375195, 2660681189, 1973518054, 2590184920,
27595 1801997909, 2225743211, 1872600680, 2153772374, 1652813359, 2369881361, 1719025170, 2310296876,
27596 1594986313, 2966676599, 1541693300, 3022402634, 1459236659, 3107472397, 1376780046, 3184366640,
27597 1288097725, 2734990467, 1211309952, 2817619134, 1160605639, 2867791097, 1104723962, 2920993988,
27598 937561457, 3626001999, 857201996, 3704993394, 1040821515, 3519792693, 989625654, 3577615880,
27599 607473029, 3421972155, 549494200, 3473077894, 769584639, 3256649409, 690699714, 3337180924,
27600 273452185, 4287555495, 347692196, 4219156378, 430386403, 4133832669, 491977950, 4069562336,
27601 60542061, 3965298515, 124656720, 3903616878, 175139863, 3853649705, 243645482, 3779581716,
27602 }, {
27603 0, 3247366080, 1483520449, 2581751297, 2967040898, 1901571138, 3904227907, 691737987,
27604 3133399365, 2068659845, 3803142276, 589399876, 169513671, 3415493895, 1383475974, 2482566342,
27605 2935407819, 1870142219, 4137319690, 924099274, 506443593, 3751897225, 1178799752, 2278412616,
27606 339027342, 3585866318, 1280941135, 2379694991, 2766951948, 1700956620, 4236308429, 1024339981,
27607 2258407383, 1192382487, 3740284438, 528411094, 910556245, 4157285269, 1848198548, 2946996820,
27608 1012887186, 4258378066, 1681119059, 2780629139, 2357599504, 1292419792, 3572147409, 358906641,
27609 678054684, 3924071644, 1879503581, 2978491677, 2561882270, 1497229150, 3235873119, 22109855,
27610 2460592729, 1395094937, 3401913240, 189516888, 577821147, 3825075739, 2048679962, 3146956762,
27611 3595049455, 398902831, 2384764974, 1336573934, 1720805997, 2803873197, 1056822188, 4285729900,
27612 1821112490, 2902796138, 887570795, 4117339819, 3696397096, 500978920, 2218668777, 1169222953,
27613 2025774372, 3106931428, 550659301, 3780950821, 3362238118, 166293862, 2416645991, 1367722151,
27614 3262987361, 66315169, 2584839584, 1537170016, 1923370979, 3005911075, 717813282, 3947244002,
27615 1356109368, 2438613496, 146288633, 3375820857, 3759007162, 562248314, 3093388411, 2045739963,
27616 3927406461, 731490493, 2994458300, 1945440636, 1523451135, 2604718911, 44219710, 3274466046,
27617 4263662323, 1068272947, 2790189874, 1740649714, 1325080945, 2406874801, 379033776, 3608758128,
27618 1155642294, 2238671990, 479005303, 3708016055, 4097359924, 901128180, 2891217397, 1843045941,
27619 2011248031, 3060787807, 797805662, 3993195422, 3342353949, 112630237, 2673147868, 1591353372,
27620 3441611994, 212601626, 2504944923, 1421914843, 2113644376, 3161815192, 630660761, 3826893145,
27621 3642224980, 412692116, 2172340373, 1089836885, 1775141590, 2822790422, 832715543, 4029474007,
27622 1674842129, 2723860433, 1001957840, 4197873168, 3540870035, 310623315, 2338445906, 1257178514,
27623 4051548744, 821257608, 2836464521, 1755307081, 1101318602, 2150241802, 432566283, 3628511179,
27624 1270766349, 2318435533, 332587724, 3529260300, 4217841807, 988411727, 2735444302, 1652903566,
27625 1602977411, 2651169091, 132630338, 3328776322, 4015131905, 786223809, 3074340032, 1991273216,
27626 3846741958, 616972294, 3173262855, 2091579847, 1435626564, 2485072772, 234706309, 3430124101,
27627 2712218736, 1613231024, 4190475697, 944458353, 292577266, 3506339890, 1226630707, 2291284467,
27628 459984181, 3672380149, 1124496628, 2189994804, 2880683703, 1782407543, 4091479926, 844224694,
27629 257943739, 3469817723, 1462980986, 2529005242, 3213269817, 2114471161, 3890881272, 644152632,
27630 3046902270, 1947391550, 3991973951, 746483711, 88439420, 3301680572, 1563018173, 2628197501,
27631 657826727, 3871046759, 2136545894, 3201811878, 2548879397, 1449267173, 3481299428, 235845156,
27632 2650161890, 1551408418, 3315268387, 68429027, 758067552, 3970035360, 1967360161, 3033356129,
27633 2311284588, 1213053100, 3517963949, 270598509, 958010606, 4170500910, 1635167535, 2700636911,
27634 855672361, 4069415401, 1802256360, 2866995240, 2212099499, 1113008747, 3686091882, 440112042,
27635 }, {
27636 0, 2611301487, 3963330207, 2006897392, 50740095, 2560849680, 4013794784, 1956178319,
27637 101480190, 2645113489, 3929532513, 1905435662, 84561281, 2662269422, 3912356638, 1922342769,
27638 202960380, 2545787283, 3760419683, 2072395532, 253679235, 2495322860, 3810871324, 2021655667,
27639 169122562, 2444351341, 3861841309, 2106214898, 152215677, 2461527058, 3844685538, 2123133581,
27640 405920760, 2207553431, 4094313831, 1873742088, 456646791, 2157096168, 4144791064, 1823027831,
27641 507358470, 2241388905, 4060492697, 1772322806, 490444409, 2258557462, 4043311334, 1789215881,
27642 338245124, 2408348267, 4161972379, 1672996084, 388959611, 2357870868, 4212429796, 1622269835,
27643 304431354, 2306870421, 4263435877, 1706791434, 287538053, 2324051946, 4246267162, 1723705717,
27644 811841520, 2881944479, 3696765295, 1207788800, 862293135, 2831204576, 3747484176, 1157324415,
27645 913293582, 2915732833, 3662962577, 1106318334, 896137841, 2932651550, 3646055662, 1123494017,
27646 1014716940, 2816349795, 3493905555, 1273334012, 1065181555, 2765630748, 3544645612, 1222882179,
27647 980888818, 2714919069, 3595350637, 1307180546, 963712909, 2731826146, 3578431762, 1324336509,
27648 676490248, 3019317351, 3295277719, 1607253752, 726947703, 2968591128, 3345992168, 1556776327,
27649 777919222, 3053147801, 3261432937, 1505806342, 760750473, 3070062054, 3244539670, 1522987897,
27650 608862708, 3220163995, 3362856811, 1406423812, 659339915, 3169449700, 3413582868, 1355966587,
27651 575076106, 3118709605, 3464325525, 1440228858, 557894773, 3135602714, 3447411434, 1457397381,
27652 1623683040, 4217512847, 2365387135, 391757072, 1673614495, 4167309552, 2415577600, 341804655,
27653 1724586270, 4251866481, 2331019137, 290835438, 1707942497, 4268256782, 2314648830, 307490961,
27654 1826587164, 4152020595, 2162433155, 457265388, 1876539747, 4101829900, 2212636668, 407333779,
27655 1792275682, 4051089549, 2263378557, 491595282, 1775619997, 4067460082, 2246988034, 508239213,
27656 2029433880, 3813931127, 2496473735, 258500328, 2079362919, 3763716872, 2546668024, 208559511,
27657 2130363110, 3848244873, 2462145657, 157552662, 2113730969, 3864638966, 2445764358, 174205801,
27658 1961777636, 4014675339, 2564147067, 57707284, 2011718299, 3964481268, 2614361092, 7778411,
27659 1927425818, 3913769845, 2665066885, 92077546, 1910772837, 3930150922, 2648673018, 108709525,
27660 1352980496, 3405878399, 3164554895, 658115296, 1403183983, 3355946752, 3214507504, 607924639,
27661 1453895406, 3440239233, 3130208369, 557218846, 1437504913, 3456883198, 3113552654, 573589345,
27662 1555838444, 3340335491, 2961681267, 723707676, 1606028947, 3290383100, 3011612684, 673504355,
27663 1521500946, 3239382909, 3062619533, 758026722, 1505130605, 3256038402, 3045975794, 774417053,
27664 1217725416, 3543158663, 2762906999, 1057739032, 1267939479, 3493229816, 2812847624, 1007544935,
27665 1318679830, 3577493881, 2728586121, 956803046, 1302285929, 3594125830, 2711933174, 973184153,
27666 1150152212, 3743982203, 2830528651, 856898788, 1200346475, 3694041348, 2880457716, 806684571,
27667 1115789546, 3643069573, 2931426933, 891243034, 1099408277, 3659722746, 2914794762, 907637093,
27668 }, {
27669 0, 3717650821, 1616688459, 3184159950, 3233376918, 489665299, 2699419613, 2104690264,
27670 1510200173, 2274691816, 979330598, 3888758691, 2595928571, 1194090622, 4209380528, 661706037,
27671 3020400346, 1771143007, 3562738577, 164481556, 1958661196, 2837976521, 350386439, 3379863682,
27672 3993269687, 865250354, 2388181244, 1406015865, 784146209, 4079732388, 1323412074, 2474079215,
27673 3011398645, 1860735600, 3542286014, 246687547, 1942430051, 2924607718, 328963112, 3456978349,
27674 3917322392, 887832861, 2300653011, 1421341782, 700772878, 4099025803, 1234716485, 2483986112,
27675 125431087, 3673109674, 1730500708, 3132326369, 3351283641, 441867836, 2812031730, 2047535991,
27676 1568292418, 2163009479, 1025936137, 3769651852, 2646824148, 1079348561, 4255113631, 537475098,
27677 3180171691, 1612400686, 3721471200, 4717925, 2100624189, 2694980280, 493375094, 3237910515,
27678 3884860102, 974691139, 2278750093, 1514417672, 657926224, 4204917205, 1198234907, 2600289438,
27679 160053105, 3558665972, 1775665722, 3024116671, 3375586791, 346391650, 2842683564, 1962488105,
27680 1401545756, 2384412057, 869618007, 3997403346, 2469432970, 1319524111, 4083956673, 788193860,
27681 250862174, 3546612699, 1856990997, 3006903952, 3461001416, 333211981, 2920678787, 1937824774,
27682 1425017139, 2305216694, 883735672, 3912918525, 2487837605, 1239398944, 4095071982, 696455019,
27683 3136584836, 1734518017, 3668494799, 121507914, 2051872274, 2816200599, 437363545, 3347544796,
27684 3774328809, 1029797484, 2158697122, 1564328743, 542033279, 4258798842, 1074950196, 2642717105,
27685 2691310871, 2113731730, 3224801372, 497043929, 1624461185, 3175454212, 9435850, 3709412175,
27686 4201248378, 671035391, 2587181873, 1201904308, 986750188, 3880142185, 1519135143, 2266689570,
27687 342721485, 3388693064, 1949382278, 2846355203, 3570723163, 155332830, 3028835344, 1763607957,
27688 1315852448, 2482538789, 775087595, 4087626862, 2396469814, 1396827059, 4002123645, 857560824,
27689 320106210, 3464673127, 1934154665, 2933785132, 3551331444, 238804465, 3018961215, 1852270778,
27690 1226292623, 2491507722, 692783300, 4108177729, 2309936921, 1412959900, 3924976210, 879016919,
27691 2803091512, 2055541181, 3343875443, 450471158, 1739236014, 3124525867, 133568485, 3663777376,
27692 4245691221, 545702608, 2639048222, 1088059291, 1034514883, 3762268230, 1576387720, 2153979149,
27693 501724348, 3228659001, 2109407735, 2687359090, 3713981994, 13109167, 3171052385, 1620357860,
27694 1206151121, 2591211092, 666423962, 4197321503, 2271022407, 1523307714, 3875649548, 982999433,
27695 2850034278, 1953942499, 3384583981, 338329256, 1767471344, 3033506165, 151375291, 3566408766,
27696 4091789579, 779425934, 2478797888, 1311354309, 861580189, 4006375960, 1392910038, 2391852883,
27697 2929327945, 1930372812, 3469036034, 324244359, 1847629279, 3015068762, 243015828, 3555391761,
27698 4103744548, 688715169, 2496043375, 1229996266, 874727090, 3920994103, 1417671673, 2313759356,
27699 446585235, 3339223062, 2059594968, 2807313757, 3660002053, 129100416, 3128657486, 1743609803,
27700 1084066558, 2634765179, 549535669, 4250396208, 2149900392, 1571961325, 3765982499, 1039043750,
27701 }, {
27702 0, 2635063670, 3782132909, 2086741467, 430739227, 2225303149, 4173482934, 1707977408,
27703 861478454, 2924937024, 3526875803, 1329085421, 720736557, 3086643291, 3415954816, 1452586230,
27704 1722956908, 4223524122, 2279405761, 450042295, 2132718455, 3792785921, 2658170842, 58693292,
27705 1441473114, 3370435372, 3028674295, 696911745, 1279765825, 3511176247, 2905172460, 807831706,
27706 3445913816, 1349228974, 738901109, 2969918723, 3569940419, 1237784245, 900084590, 2829701656,
27707 4265436910, 1664255896, 525574723, 2187084597, 3885099509, 2057177219, 117386584, 2616249390,
27708 2882946228, 920233410, 1253605401, 3619119471, 2994391983, 796207833, 1393823490, 3457937012,
27709 2559531650, 92322804, 2044829231, 3840835417, 2166609305, 472659183, 1615663412, 4249022530,
27710 1102706673, 3702920839, 2698457948, 1037619754, 1477802218, 3306854812, 3111894087, 611605809,
27711 1927342535, 4025419953, 2475568490, 243387420, 1800169180, 4131620778, 2317525617, 388842247,
27712 655084445, 3120835307, 3328511792, 1533734470, 1051149446, 2745738736, 3754524715, 1120297309,
27713 340972971, 2304586973, 4114354438, 1748234352, 234773168, 2431761350, 3968900637, 1906278251,
27714 2363330345, 299003487, 1840466820, 4038896370, 2507210802, 142532932, 1948239007, 3910149609,
27715 3213136159, 579563625, 1592415666, 3286611140, 2787646980, 992477042, 1195825833, 3662232543,
27716 3933188933, 2002801203, 184645608, 2517538462, 4089658462, 1858919720, 313391347, 2409765253,
27717 3644239219, 1144605701, 945318366, 2773977256, 3231326824, 1570095902, 569697989, 3170568115,
27718 2205413346, 511446676, 1646078799, 4279421497, 2598330617, 131105167, 2075239508, 3871229218,
27719 2955604436, 757403810, 1363424633, 3427521551, 2844163791, 881434553, 1223211618, 3588709140,
27720 3854685070, 2026779384, 78583587, 2577462869, 4235025557, 1633861091, 486774840, 2148301134,
27721 3600338360, 1268198606, 938871061, 2868504675, 3476308643, 1379640277, 777684494, 3008718712,
27722 1310168890, 3541595724, 2943964055, 846639841, 1471879201, 3400857943, 3067468940, 735723002,
27723 2102298892, 3762382970, 2619362721, 19901655, 1692534295, 4193118049, 2240594618, 411247564,
27724 681945942, 3047836192, 3385552891, 1422167693, 822682701, 2886124859, 3496468704, 1298661782,
27725 469546336, 2264093718, 4203901389, 1738379451, 38812283, 2673859341, 3812556502, 2117148576,
27726 3268024339, 1606809957, 598006974, 3198893512, 3680933640, 1181316734, 973624229, 2802299603,
27727 4052944421, 1822222163, 285065864, 2381456382, 3896478014, 1966106696, 156323219, 2489232613,
27728 2759337087, 964150537, 1159127250, 3625517476, 3184831332, 551242258, 1555722185, 3249901247,
27729 2535537225, 170842943, 1984954084, 3946848146, 2391651666, 327308324, 1877176831, 4075589769,
27730 263086283, 2460058045, 4005602406, 1942963472, 369291216, 2332888742, 4151061373, 1784924683,
27731 1022852861, 2717425547, 3717839440, 1083595558, 626782694, 3092517008, 3291821387, 1497027645,
27732 1763466407, 4094934481, 2289211402, 360544636, 1890636732, 3988730570, 2447251217, 215086695,
27733 1514488465, 3343557607, 3140191804, 639919946, 1139395978, 3739626748, 2726758695, 1065936977,
27734 }, {
27735 0, 3120290792, 2827399569, 293431929, 2323408227, 864534155, 586863858, 2600537882,
27736 3481914503, 1987188591, 1729068310, 3740575486, 1173727716, 4228805132, 3983743093, 1418249117,
27737 1147313999, 4254680231, 3974377182, 1428157750, 3458136620, 2011505092, 1721256893, 3747844181,
27738 2347455432, 839944224, 594403929, 2593536433, 26687147, 3094146371, 2836498234, 283794642,
27739 2294627998, 826205558, 541298447, 2578994407, 45702141, 3141697557, 2856315500, 331624836,
27740 1196225049, 4273416689, 4023010184, 1446090848, 3442513786, 1959480466, 1706436331, 3696098563,
27741 3433538001, 1968994873, 1679888448, 3722103720, 1188807858, 4280295258, 3999102243, 1470541515,
27742 53374294, 3134568126, 2879970503, 307431215, 2303854645, 816436189, 567589284, 2553242188,
27743 3405478781, 1929420949, 1652411116, 3682996484, 1082596894, 4185703926, 3892424591, 1375368295,
27744 91404282, 3163122706, 2918450795, 336584067, 2400113305, 922028401, 663249672, 2658384096,
27745 2392450098, 929185754, 639587747, 2682555979, 82149713, 3172883129, 2892181696, 362343208,
27746 1091578037, 4176212829, 3918960932, 1349337804, 3412872662, 1922537022, 1676344391, 3658557359,
27747 1111377379, 4224032267, 3937989746, 1396912026, 3359776896, 1908013928, 1623494929, 3644803833,
27748 2377615716, 877417100, 623982837, 2630542109, 130804743, 3190831087, 2941083030, 381060734,
27749 106748588, 3215393092, 2933549885, 388083925, 2350956495, 903570471, 614862430, 2640172470,
27750 3386185259, 1882115523, 1632872378, 3634920530, 1135178568, 4199721120, 3945775833, 1389631793,
27751 1317531835, 4152109907, 3858841898, 1610259138, 3304822232, 2097172016, 1820140617, 3582394273,
27752 2165193788, 955639764, 696815021, 2423477829, 192043359, 2995356343, 2750736590, 437203750,
27753 182808564, 3005133852, 2724453989, 462947725, 2157513367, 962777471, 673168134, 2447663342,
27754 3312231283, 2090301595, 1844056802, 3557935370, 1326499344, 4142603768, 3885397889, 1584245865,
27755 3326266917, 2142836173, 1858371508, 3611272284, 1279175494, 4123357358, 3837270743, 1564721471,
27756 164299426, 2955991370, 2706223923, 414607579, 2209834945, 978107433, 724686416, 2462715320,
27757 2183156074, 1004243586, 715579643, 2472360723, 140260361, 2980573153, 2698675608, 421617264,
27758 1302961645, 4099032581, 3845074044, 1557460884, 3352688782, 2116952934, 1867729183, 3601371895,
27759 2222754758, 1032278062, 754596439, 2499928511, 234942117, 3086693709, 2793824052, 528319708,
27760 1274365761, 4061043881, 3816027856, 1518873912, 3246989858, 2020800970, 1762628531, 3505670235,
27761 3223196809, 2045103969, 1754834200, 3512958704, 1247965674, 4086934018, 3806642299, 1528765331,
27762 261609486, 3060532198, 2802936223, 518697591, 2246819181, 1007707781, 762121468, 2492913428,
27763 213497176, 3041029808, 2755593417, 499441441, 2261110843, 1061030867, 776167850, 2545465922,
27764 3274734047, 2060165687, 1807140942, 3528266662, 1229724860, 4038575956, 3788156205, 1479636677,
27765 1222322711, 4045468159, 3764231046, 1504067694, 3265744756, 2069664924, 1780612837, 3554288909,
27766 2270357136, 1051278712, 802445057, 2519698665, 221152243, 3033880603, 2779263586, 475261322,
27767 }, {
27768 0, 2926088593, 2275419491, 701019378, 3560000647, 2052709654, 1402038756, 4261017717,
27769 1930665807, 3715829470, 4105419308, 1524313021, 2804077512, 155861593, 545453739, 2397726522,
27770 3861331614, 1213181711, 1636244477, 3488582252, 840331801, 2625561480, 3048626042, 467584747,
27771 2503254481, 995897408, 311723186, 3170637091, 1090907478, 4016929991, 3332753461, 1758288292,
27772 390036349, 3109546732, 2426363422, 1056427919, 3272488954, 1835443819, 1152258713, 3938878216,
27773 1680663602, 3393484195, 3817652561, 1306808512, 2954733749, 510998820, 935169494, 2580880455,
27774 4044899811, 1601229938, 1991794816, 3637571857, 623446372, 2336332021, 2726898695, 216120726,
27775 2181814956, 744704829, 95158223, 2881711710, 1446680107, 4166125498, 3516576584, 2146575065,
27776 780072698, 2148951915, 2849952665, 129384968, 4199529085, 1411853292, 2112855838, 3548843663,
27777 1567451573, 4077254692, 3670887638, 1957027143, 2304517426, 657765539, 251396177, 2694091200,
27778 3361327204, 1714510325, 1341779207, 3784408214, 476611811, 2986349938, 2613617024, 899690513,
27779 3142211371, 354600634, 1021997640, 2458051545, 1870338988, 3239283261, 3906682575, 1186180958,
27780 960597383, 2536053782, 3202459876, 277428597, 3983589632, 1125666961, 1792074851, 3300423154,
27781 1246892744, 3829039961, 3455203243, 1671079482, 2657312335, 806080478, 432241452, 3081497277,
27782 3748049689, 1896751752, 1489409658, 4138600427, 190316446, 2772397583, 2365053693, 580864876,
27783 2893360214, 35503559, 735381813, 2243795108, 2017747153, 3593269568, 4293150130, 1368183843,
27784 1560145396, 4069882981, 3680356503, 1966430470, 2295112051, 648294626, 258769936, 2701399425,
27785 804156091, 2173100842, 2823706584, 103204425, 4225711676, 1438101421, 2088704863, 3524758222,
27786 3134903146, 347226875, 1031468553, 2467456920, 1860935661, 3229814396, 3914054286, 1193487135,
27787 3385412645, 1738661300, 1315531078, 3758225623, 502792354, 3012596019, 2589468097, 875607120,
27788 1271043721, 3853125400, 3429020650, 1644831355, 2683558414, 832261023, 408158061, 3057348348,
27789 953223622, 2528745559, 3211865253, 286899508, 3974120769, 1116263632, 1799381026, 3307794867,
27790 2917509143, 59586950, 709201268, 2217549029, 2043995280, 3619452161, 4269064691, 1344032866,
27791 3740677976, 1889445577, 1498812987, 4148069290, 180845535, 2762992206, 2372361916, 588238637,
27792 1921194766, 3706423967, 4112727661, 1531686908, 2796705673, 148555288, 554857194, 2407195515,
27793 26248257, 2952271312, 2251333922, 676868275, 3584149702, 2076793175, 1375858085, 4234771508,
27794 2493785488, 986493953, 319029491, 3178008930, 1083533591, 4009621638, 3342158964, 1767759333,
27795 3887577823, 1239362382, 1612160956, 3464433197, 864482904, 2649647049, 3022443323, 441336490,
27796 1706844275, 3419730402, 3793503504, 1282724993, 2978819316, 535149925, 908921239, 2554697734,
27797 380632892, 3100077741, 2433735263, 1063734222, 3265180603, 1828069930, 1161729752, 3948283721,
27798 2207997677, 770953084, 71007118, 2857626143, 1470763626, 4190274555, 3490330377, 2120394392,
27799 4035494306, 1591758899, 1999168705, 3644880208, 616140069, 2328960180, 2736367686, 225524183,
27800 },
27801};
27802
27803static const uint8_t
27804WUFFS_CRC32__IEEE_X86_SSE42_K1K2[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
27805 212, 43, 68, 84, 1, 0, 0, 0,
27806 150, 21, 228, 198, 1, 0, 0, 0,
27807};
27808
27809static const uint8_t
27810WUFFS_CRC32__IEEE_X86_SSE42_K3K4[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
27811 208, 151, 25, 117, 1, 0, 0, 0,
27812 158, 0, 170, 204, 0, 0, 0, 0,
27813};
27814
27815static const uint8_t
27816WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
27817 36, 97, 205, 99, 1, 0, 0, 0,
27818 0, 0, 0, 0, 0, 0, 0, 0,
27819};
27820
27821static const uint8_t
27822WUFFS_CRC32__IEEE_X86_SSE42_PXMU[16] WUFFS_BASE__POTENTIALLY_UNUSED = {
27823 65, 6, 113, 219, 1, 0, 0, 0,
27824 65, 22, 1, 247, 1, 0, 0, 0,
27825};
27826
27827// ---------------- Private Initializer Prototypes
27828
27829// ---------------- Private Function Prototypes
27830
27831static wuffs_base__empty_struct
27832wuffs_crc32__ieee_hasher__up(
27833 wuffs_crc32__ieee_hasher* self,
27834 wuffs_base__slice_u8 a_x);
27835
27836static wuffs_base__empty_struct
27837wuffs_crc32__ieee_hasher__up__choosy_default(
27838 wuffs_crc32__ieee_hasher* self,
27839 wuffs_base__slice_u8 a_x);
27840
27841#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
27842static wuffs_base__empty_struct
27843wuffs_crc32__ieee_hasher__up_arm_crc32(
27844 wuffs_crc32__ieee_hasher* self,
27845 wuffs_base__slice_u8 a_x);
27846#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
27847
Nigel Tao7804ffe2021-10-07 21:58:26 +110027848#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100027849static wuffs_base__empty_struct
Nigel Tao5571bfe2021-06-24 22:44:29 +100027850wuffs_crc32__ieee_hasher__up_x86_avx2(
27851 wuffs_crc32__ieee_hasher* self,
27852 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110027853#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100027854
Nigel Tao7804ffe2021-10-07 21:58:26 +110027855#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100027856static wuffs_base__empty_struct
Nigel Taoe360a532021-04-05 22:47:03 +100027857wuffs_crc32__ieee_hasher__up_x86_sse42(
27858 wuffs_crc32__ieee_hasher* self,
27859 wuffs_base__slice_u8 a_x);
Nigel Tao7804ffe2021-10-07 21:58:26 +110027860#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100027861
27862// ---------------- VTables
27863
27864const wuffs_base__hasher_u32__func_ptrs
27865wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32 = {
27866 (wuffs_base__empty_struct(*)(void*,
27867 uint32_t,
27868 bool))(&wuffs_crc32__ieee_hasher__set_quirk_enabled),
27869 (uint32_t(*)(void*,
27870 wuffs_base__slice_u8))(&wuffs_crc32__ieee_hasher__update_u32),
27871};
27872
27873// ---------------- Initializer Implementations
27874
27875wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
27876wuffs_crc32__ieee_hasher__initialize(
27877 wuffs_crc32__ieee_hasher* self,
27878 size_t sizeof_star_self,
27879 uint64_t wuffs_version,
27880 uint32_t options){
27881 if (!self) {
27882 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
27883 }
27884 if (sizeof(*self) != sizeof_star_self) {
27885 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
27886 }
27887 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
27888 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
27889 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
27890 }
27891
27892 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
27893 // The whole point of this if-check is to detect an uninitialized *self.
27894 // We disable the warning on GCC. Clang-5.0 does not have this warning.
27895#if !defined(__clang__) && defined(__GNUC__)
27896#pragma GCC diagnostic push
27897#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
27898#endif
27899 if (self->private_impl.magic != 0) {
27900 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
27901 }
27902#if !defined(__clang__) && defined(__GNUC__)
27903#pragma GCC diagnostic pop
27904#endif
27905 } else {
27906 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
27907 memset(self, 0, sizeof(*self));
27908 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
27909 } else {
27910 memset(&(self->private_impl), 0, sizeof(self->private_impl));
27911 }
27912 }
27913
27914 self->private_impl.choosy_up = &wuffs_crc32__ieee_hasher__up__choosy_default;
27915
27916 self->private_impl.magic = WUFFS_BASE__MAGIC;
27917 self->private_impl.vtable_for__wuffs_base__hasher_u32.vtable_name =
27918 wuffs_base__hasher_u32__vtable_name;
27919 self->private_impl.vtable_for__wuffs_base__hasher_u32.function_pointers =
27920 (const void*)(&wuffs_crc32__ieee_hasher__func_ptrs_for__wuffs_base__hasher_u32);
27921 return wuffs_base__make_status(NULL);
27922}
27923
27924wuffs_crc32__ieee_hasher*
27925wuffs_crc32__ieee_hasher__alloc() {
27926 wuffs_crc32__ieee_hasher* x =
27927 (wuffs_crc32__ieee_hasher*)(calloc(sizeof(wuffs_crc32__ieee_hasher), 1));
27928 if (!x) {
27929 return NULL;
27930 }
27931 if (wuffs_crc32__ieee_hasher__initialize(
27932 x, sizeof(wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
27933 free(x);
27934 return NULL;
27935 }
27936 return x;
27937}
27938
27939size_t
27940sizeof__wuffs_crc32__ieee_hasher() {
27941 return sizeof(wuffs_crc32__ieee_hasher);
27942}
27943
27944// ---------------- Function Implementations
27945
27946// -------- func crc32.ieee_hasher.set_quirk_enabled
27947
27948WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
27949wuffs_crc32__ieee_hasher__set_quirk_enabled(
27950 wuffs_crc32__ieee_hasher* self,
27951 uint32_t a_quirk,
27952 bool a_enabled) {
27953 return wuffs_base__make_empty_struct();
27954}
27955
27956// -------- func crc32.ieee_hasher.update_u32
27957
27958WUFFS_BASE__MAYBE_STATIC uint32_t
27959wuffs_crc32__ieee_hasher__update_u32(
27960 wuffs_crc32__ieee_hasher* self,
27961 wuffs_base__slice_u8 a_x) {
27962 if (!self) {
27963 return 0;
27964 }
27965 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
27966 return 0;
27967 }
27968
27969 if (self->private_impl.f_state == 0) {
27970 self->private_impl.choosy_up = (
27971#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
27972 wuffs_base__cpu_arch__have_arm_crc32() ? &wuffs_crc32__ieee_hasher__up_arm_crc32 :
27973#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110027974#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100027975 wuffs_base__cpu_arch__have_x86_avx2() ? &wuffs_crc32__ieee_hasher__up_x86_avx2 :
27976#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110027977#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100027978 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_crc32__ieee_hasher__up_x86_sse42 :
27979#endif
27980 self->private_impl.choosy_up);
27981 }
27982 wuffs_crc32__ieee_hasher__up(self, a_x);
27983 return self->private_impl.f_state;
27984}
27985
27986// -------- func crc32.ieee_hasher.up
27987
27988static wuffs_base__empty_struct
27989wuffs_crc32__ieee_hasher__up(
27990 wuffs_crc32__ieee_hasher* self,
27991 wuffs_base__slice_u8 a_x) {
27992 return (*self->private_impl.choosy_up)(self, a_x);
27993}
27994
27995static wuffs_base__empty_struct
27996wuffs_crc32__ieee_hasher__up__choosy_default(
27997 wuffs_crc32__ieee_hasher* self,
27998 wuffs_base__slice_u8 a_x) {
27999 uint32_t v_s = 0;
28000 wuffs_base__slice_u8 v_p = {0};
28001
28002 v_s = (4294967295 ^ self->private_impl.f_state);
28003 {
28004 wuffs_base__slice_u8 i_slice_p = a_x;
28005 v_p.ptr = i_slice_p.ptr;
28006 v_p.len = 16;
28007 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 32) * 32);
28008 while (v_p.ptr < i_end0_p) {
28009 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
28010 (((uint32_t)(v_p.ptr[1])) << 8) |
28011 (((uint32_t)(v_p.ptr[2])) << 16) |
28012 (((uint32_t)(v_p.ptr[3])) << 24));
28013 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
28014 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
28015 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
28016 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
28017 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
28018 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
28019 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
28020 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
28021 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
28022 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
28023 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
28024 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
28025 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
28026 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
28027 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
28028 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
28029 v_p.ptr += 16;
28030 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
28031 (((uint32_t)(v_p.ptr[1])) << 8) |
28032 (((uint32_t)(v_p.ptr[2])) << 16) |
28033 (((uint32_t)(v_p.ptr[3])) << 24));
28034 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
28035 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
28036 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
28037 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
28038 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
28039 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
28040 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
28041 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
28042 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
28043 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
28044 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
28045 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
28046 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
28047 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
28048 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
28049 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
28050 v_p.ptr += 16;
28051 }
28052 v_p.len = 16;
28053 uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 16) * 16);
28054 while (v_p.ptr < i_end1_p) {
28055 v_s ^= ((((uint32_t)(v_p.ptr[0])) << 0) |
28056 (((uint32_t)(v_p.ptr[1])) << 8) |
28057 (((uint32_t)(v_p.ptr[2])) << 16) |
28058 (((uint32_t)(v_p.ptr[3])) << 24));
28059 v_s = (WUFFS_CRC32__IEEE_TABLE[0][v_p.ptr[15]] ^
28060 WUFFS_CRC32__IEEE_TABLE[1][v_p.ptr[14]] ^
28061 WUFFS_CRC32__IEEE_TABLE[2][v_p.ptr[13]] ^
28062 WUFFS_CRC32__IEEE_TABLE[3][v_p.ptr[12]] ^
28063 WUFFS_CRC32__IEEE_TABLE[4][v_p.ptr[11]] ^
28064 WUFFS_CRC32__IEEE_TABLE[5][v_p.ptr[10]] ^
28065 WUFFS_CRC32__IEEE_TABLE[6][v_p.ptr[9]] ^
28066 WUFFS_CRC32__IEEE_TABLE[7][v_p.ptr[8]] ^
28067 WUFFS_CRC32__IEEE_TABLE[8][v_p.ptr[7]] ^
28068 WUFFS_CRC32__IEEE_TABLE[9][v_p.ptr[6]] ^
28069 WUFFS_CRC32__IEEE_TABLE[10][v_p.ptr[5]] ^
28070 WUFFS_CRC32__IEEE_TABLE[11][v_p.ptr[4]] ^
28071 WUFFS_CRC32__IEEE_TABLE[12][(255 & (v_s >> 24))] ^
28072 WUFFS_CRC32__IEEE_TABLE[13][(255 & (v_s >> 16))] ^
28073 WUFFS_CRC32__IEEE_TABLE[14][(255 & (v_s >> 8))] ^
28074 WUFFS_CRC32__IEEE_TABLE[15][(255 & (v_s >> 0))]);
28075 v_p.ptr += 16;
28076 }
28077 v_p.len = 1;
28078 uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len;
28079 while (v_p.ptr < i_end2_p) {
28080 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
28081 v_p.ptr += 1;
28082 }
28083 v_p.len = 0;
28084 }
28085 self->private_impl.f_state = (4294967295 ^ v_s);
28086 return wuffs_base__make_empty_struct();
28087}
28088
28089// ‼ WUFFS MULTI-FILE SECTION +arm_crc32
28090// -------- func crc32.ieee_hasher.up_arm_crc32
28091
28092#if defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
28093static wuffs_base__empty_struct
28094wuffs_crc32__ieee_hasher__up_arm_crc32(
28095 wuffs_crc32__ieee_hasher* self,
28096 wuffs_base__slice_u8 a_x) {
28097 wuffs_base__slice_u8 v_p = {0};
28098 uint32_t v_s = 0;
28099
28100 v_s = (4294967295 ^ self->private_impl.f_state);
28101 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
28102 v_s = __crc32b(v_s, a_x.ptr[0]);
28103 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
28104 }
28105 {
28106 wuffs_base__slice_u8 i_slice_p = a_x;
28107 v_p.ptr = i_slice_p.ptr;
28108 v_p.len = 8;
28109 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 128) * 128);
28110 while (v_p.ptr < i_end0_p) {
28111 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28112 v_p.ptr += 8;
28113 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28114 v_p.ptr += 8;
28115 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28116 v_p.ptr += 8;
28117 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28118 v_p.ptr += 8;
28119 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28120 v_p.ptr += 8;
28121 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28122 v_p.ptr += 8;
28123 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28124 v_p.ptr += 8;
28125 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28126 v_p.ptr += 8;
28127 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28128 v_p.ptr += 8;
28129 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28130 v_p.ptr += 8;
28131 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28132 v_p.ptr += 8;
28133 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28134 v_p.ptr += 8;
28135 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28136 v_p.ptr += 8;
28137 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28138 v_p.ptr += 8;
28139 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28140 v_p.ptr += 8;
28141 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28142 v_p.ptr += 8;
28143 }
28144 v_p.len = 8;
28145 uint8_t* i_end1_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 8) * 8);
28146 while (v_p.ptr < i_end1_p) {
28147 v_s = __crc32d(v_s, wuffs_base__peek_u64le__no_bounds_check(v_p.ptr));
28148 v_p.ptr += 8;
28149 }
28150 v_p.len = 1;
28151 uint8_t* i_end2_p = i_slice_p.ptr + i_slice_p.len;
28152 while (v_p.ptr < i_end2_p) {
28153 v_s = __crc32b(v_s, v_p.ptr[0]);
28154 v_p.ptr += 1;
28155 }
28156 v_p.len = 0;
28157 }
28158 self->private_impl.f_state = (4294967295 ^ v_s);
28159 return wuffs_base__make_empty_struct();
28160}
28161#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_CRC32)
28162// ‼ WUFFS MULTI-FILE SECTION -arm_crc32
28163
Nigel Tao5571bfe2021-06-24 22:44:29 +100028164// ‼ WUFFS MULTI-FILE SECTION +x86_avx2
28165// -------- func crc32.ieee_hasher.up_x86_avx2
28166
Nigel Tao7804ffe2021-10-07 21:58:26 +110028167#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100028168WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2,avx2")
28169static wuffs_base__empty_struct
28170wuffs_crc32__ieee_hasher__up_x86_avx2(
28171 wuffs_crc32__ieee_hasher* self,
28172 wuffs_base__slice_u8 a_x) {
28173 uint32_t v_s = 0;
28174 wuffs_base__slice_u8 v_p = {0};
28175 __m128i v_k = {0};
28176 __m128i v_x0 = {0};
28177 __m128i v_x1 = {0};
28178 __m128i v_x2 = {0};
28179 __m128i v_x3 = {0};
28180 __m128i v_y0 = {0};
28181 __m128i v_y1 = {0};
28182 __m128i v_y2 = {0};
28183 __m128i v_y3 = {0};
28184 uint64_t v_tail_index = 0;
28185
28186 v_s = (4294967295 ^ self->private_impl.f_state);
28187 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
28188 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ a_x.ptr[0])] ^ (v_s >> 8));
28189 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
28190 }
28191 if (((uint64_t)(a_x.len)) < 64) {
28192 {
28193 wuffs_base__slice_u8 i_slice_p = a_x;
28194 v_p.ptr = i_slice_p.ptr;
28195 v_p.len = 1;
28196 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
28197 while (v_p.ptr < i_end0_p) {
28198 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
28199 v_p.ptr += 1;
28200 }
28201 v_p.len = 0;
28202 }
28203 self->private_impl.f_state = (4294967295 ^ v_s);
28204 return wuffs_base__make_empty_struct();
28205 }
28206 v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0));
28207 v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16));
28208 v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32));
28209 v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48));
28210 v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s)));
28211 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2));
28212 {
28213 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64);
28214 v_p.ptr = i_slice_p.ptr;
28215 v_p.len = 64;
28216 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64);
28217 while (v_p.ptr < i_end0_p) {
28218 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28219 v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
28220 v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0));
28221 v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0));
28222 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28223 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17));
28224 v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17));
28225 v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17));
28226 v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0)));
28227 v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16)));
28228 v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32)));
28229 v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48)));
28230 v_p.ptr += 64;
28231 }
28232 v_p.len = 0;
28233 }
28234 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4));
28235 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28236 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28237 v_x0 = _mm_xor_si128(v_x0, v_x1);
28238 v_x0 = _mm_xor_si128(v_x0, v_y0);
28239 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28240 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28241 v_x0 = _mm_xor_si128(v_x0, v_x2);
28242 v_x0 = _mm_xor_si128(v_x0, v_y0);
28243 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28244 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28245 v_x0 = _mm_xor_si128(v_x0, v_x3);
28246 v_x0 = _mm_xor_si128(v_x0, v_y0);
28247 v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16));
28248 v_x2 = _mm_set_epi32((int32_t)(0), (int32_t)(4294967295), (int32_t)(0), (int32_t)(4294967295));
28249 v_x0 = _mm_srli_si128(v_x0, (int32_t)(8));
28250 v_x0 = _mm_xor_si128(v_x0, v_x1);
28251 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ));
28252 v_x1 = _mm_srli_si128(v_x0, (int32_t)(4));
28253 v_x0 = _mm_and_si128(v_x0, v_x2);
28254 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28255 v_x0 = _mm_xor_si128(v_x0, v_x1);
28256 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU));
28257 v_x1 = _mm_and_si128(v_x0, v_x2);
28258 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16));
28259 v_x1 = _mm_and_si128(v_x1, v_x2);
28260 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
28261 v_x0 = _mm_xor_si128(v_x0, v_x1);
28262 v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1))));
28263 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u);
28264 if (v_tail_index < ((uint64_t)(a_x.len))) {
28265 {
28266 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
28267 v_p.ptr = i_slice_p.ptr;
28268 v_p.len = 1;
28269 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
28270 while (v_p.ptr < i_end0_p) {
28271 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
28272 v_p.ptr += 1;
28273 }
28274 v_p.len = 0;
28275 }
28276 }
28277 self->private_impl.f_state = (4294967295 ^ v_s);
28278 return wuffs_base__make_empty_struct();
28279}
Nigel Tao7804ffe2021-10-07 21:58:26 +110028280#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100028281// ‼ WUFFS MULTI-FILE SECTION -x86_avx2
28282
Nigel Taoe360a532021-04-05 22:47:03 +100028283// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
28284// -------- func crc32.ieee_hasher.up_x86_sse42
28285
Nigel Tao7804ffe2021-10-07 21:58:26 +110028286#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100028287WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
28288static wuffs_base__empty_struct
28289wuffs_crc32__ieee_hasher__up_x86_sse42(
28290 wuffs_crc32__ieee_hasher* self,
28291 wuffs_base__slice_u8 a_x) {
28292 uint32_t v_s = 0;
28293 wuffs_base__slice_u8 v_p = {0};
28294 __m128i v_k = {0};
28295 __m128i v_x0 = {0};
28296 __m128i v_x1 = {0};
28297 __m128i v_x2 = {0};
28298 __m128i v_x3 = {0};
28299 __m128i v_y0 = {0};
28300 __m128i v_y1 = {0};
28301 __m128i v_y2 = {0};
28302 __m128i v_y3 = {0};
28303 uint64_t v_tail_index = 0;
28304
28305 v_s = (4294967295 ^ self->private_impl.f_state);
28306 while ((((uint64_t)(a_x.len)) > 0) && ((15 & ((uint32_t)(0xFFF & (uintptr_t)(a_x.ptr)))) != 0)) {
28307 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ a_x.ptr[0])] ^ (v_s >> 8));
28308 a_x = wuffs_base__slice_u8__subslice_i(a_x, 1);
28309 }
28310 if (((uint64_t)(a_x.len)) < 64) {
28311 {
28312 wuffs_base__slice_u8 i_slice_p = a_x;
28313 v_p.ptr = i_slice_p.ptr;
28314 v_p.len = 1;
28315 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
28316 while (v_p.ptr < i_end0_p) {
28317 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
28318 v_p.ptr += 1;
28319 }
28320 v_p.len = 0;
28321 }
28322 self->private_impl.f_state = (4294967295 ^ v_s);
28323 return wuffs_base__make_empty_struct();
28324 }
28325 v_x0 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 0));
28326 v_x1 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 16));
28327 v_x2 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 32));
28328 v_x3 = _mm_lddqu_si128((const __m128i*)(const void*)(a_x.ptr + 48));
28329 v_x0 = _mm_xor_si128(v_x0, _mm_cvtsi32_si128((int32_t)(v_s)));
28330 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K1K2));
28331 {
28332 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, 64);
28333 v_p.ptr = i_slice_p.ptr;
28334 v_p.len = 64;
28335 uint8_t* i_end0_p = v_p.ptr + (((i_slice_p.len - (size_t)(v_p.ptr - i_slice_p.ptr)) / 64) * 64);
28336 while (v_p.ptr < i_end0_p) {
28337 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28338 v_y1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
28339 v_y2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(0));
28340 v_y3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(0));
28341 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28342 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(17));
28343 v_x2 = _mm_clmulepi64_si128(v_x2, v_k, (int32_t)(17));
28344 v_x3 = _mm_clmulepi64_si128(v_x3, v_k, (int32_t)(17));
28345 v_x0 = _mm_xor_si128(_mm_xor_si128(v_x0, v_y0), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 0)));
28346 v_x1 = _mm_xor_si128(_mm_xor_si128(v_x1, v_y1), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 16)));
28347 v_x2 = _mm_xor_si128(_mm_xor_si128(v_x2, v_y2), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 32)));
28348 v_x3 = _mm_xor_si128(_mm_xor_si128(v_x3, v_y3), _mm_lddqu_si128((const __m128i*)(const void*)(v_p.ptr + 48)));
28349 v_p.ptr += 64;
28350 }
28351 v_p.len = 0;
28352 }
28353 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K3K4));
28354 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28355 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28356 v_x0 = _mm_xor_si128(v_x0, v_x1);
28357 v_x0 = _mm_xor_si128(v_x0, v_y0);
28358 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28359 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28360 v_x0 = _mm_xor_si128(v_x0, v_x2);
28361 v_x0 = _mm_xor_si128(v_x0, v_y0);
28362 v_y0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28363 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(17));
28364 v_x0 = _mm_xor_si128(v_x0, v_x3);
28365 v_x0 = _mm_xor_si128(v_x0, v_y0);
28366 v_x1 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(16));
28367 v_x2 = _mm_set_epi32((int32_t)(0), (int32_t)(4294967295), (int32_t)(0), (int32_t)(4294967295));
28368 v_x0 = _mm_srli_si128(v_x0, (int32_t)(8));
28369 v_x0 = _mm_xor_si128(v_x0, v_x1);
28370 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_K5ZZ));
28371 v_x1 = _mm_srli_si128(v_x0, (int32_t)(4));
28372 v_x0 = _mm_and_si128(v_x0, v_x2);
28373 v_x0 = _mm_clmulepi64_si128(v_x0, v_k, (int32_t)(0));
28374 v_x0 = _mm_xor_si128(v_x0, v_x1);
28375 v_k = _mm_lddqu_si128((const __m128i*)(const void*)(WUFFS_CRC32__IEEE_X86_SSE42_PXMU));
28376 v_x1 = _mm_and_si128(v_x0, v_x2);
28377 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(16));
28378 v_x1 = _mm_and_si128(v_x1, v_x2);
28379 v_x1 = _mm_clmulepi64_si128(v_x1, v_k, (int32_t)(0));
28380 v_x0 = _mm_xor_si128(v_x0, v_x1);
28381 v_s = ((uint32_t)(_mm_extract_epi32(v_x0, (int32_t)(1))));
28382 v_tail_index = (((uint64_t)(a_x.len)) & 18446744073709551552u);
28383 if (v_tail_index < ((uint64_t)(a_x.len))) {
28384 {
28385 wuffs_base__slice_u8 i_slice_p = wuffs_base__slice_u8__subslice_i(a_x, v_tail_index);
28386 v_p.ptr = i_slice_p.ptr;
28387 v_p.len = 1;
28388 uint8_t* i_end0_p = i_slice_p.ptr + i_slice_p.len;
28389 while (v_p.ptr < i_end0_p) {
28390 v_s = (WUFFS_CRC32__IEEE_TABLE[0][(((uint8_t)((v_s & 255))) ^ v_p.ptr[0])] ^ (v_s >> 8));
28391 v_p.ptr += 1;
28392 }
28393 v_p.len = 0;
28394 }
28395 }
28396 self->private_impl.f_state = (4294967295 ^ v_s);
28397 return wuffs_base__make_empty_struct();
28398}
Nigel Tao7804ffe2021-10-07 21:58:26 +110028399#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100028400// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
28401
28402#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__CRC32)
28403
28404#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE)
28405
28406// ---------------- Status Codes Implementations
28407
28408const char wuffs_deflate__error__bad_huffman_code_over_subscribed[] = "#deflate: bad Huffman code (over-subscribed)";
28409const char wuffs_deflate__error__bad_huffman_code_under_subscribed[] = "#deflate: bad Huffman code (under-subscribed)";
28410const char wuffs_deflate__error__bad_huffman_code_length_count[] = "#deflate: bad Huffman code length count";
28411const char wuffs_deflate__error__bad_huffman_code_length_repetition[] = "#deflate: bad Huffman code length repetition";
28412const char wuffs_deflate__error__bad_huffman_code[] = "#deflate: bad Huffman code";
28413const char wuffs_deflate__error__bad_huffman_minimum_code_length[] = "#deflate: bad Huffman minimum code length";
28414const char wuffs_deflate__error__bad_block[] = "#deflate: bad block";
28415const char wuffs_deflate__error__bad_distance[] = "#deflate: bad distance";
28416const char wuffs_deflate__error__bad_distance_code_count[] = "#deflate: bad distance code count";
28417const char wuffs_deflate__error__bad_literal_length_code_count[] = "#deflate: bad literal/length code count";
28418const char wuffs_deflate__error__inconsistent_stored_block_length[] = "#deflate: inconsistent stored block length";
28419const char wuffs_deflate__error__missing_end_of_block_code[] = "#deflate: missing end-of-block code";
28420const char wuffs_deflate__error__no_huffman_codes[] = "#deflate: no Huffman codes";
28421const char wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state[] = "#deflate: internal error: inconsistent Huffman decoder state";
28422const char wuffs_deflate__error__internal_error_inconsistent_i_o[] = "#deflate: internal error: inconsistent I/O";
28423const char wuffs_deflate__error__internal_error_inconsistent_distance[] = "#deflate: internal error: inconsistent distance";
28424const char wuffs_deflate__error__internal_error_inconsistent_n_bits[] = "#deflate: internal error: inconsistent n_bits";
28425
28426// ---------------- Private Consts
28427
28428static const uint8_t
28429WUFFS_DEFLATE__CODE_ORDER[19] WUFFS_BASE__POTENTIALLY_UNUSED = {
28430 16, 17, 18, 0, 8, 7, 9, 6,
28431 10, 5, 11, 4, 12, 3, 13, 2,
28432 14, 1, 15,
28433};
28434
28435static const uint8_t
28436WUFFS_DEFLATE__REVERSE8[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
28437 0, 128, 64, 192, 32, 160, 96, 224,
28438 16, 144, 80, 208, 48, 176, 112, 240,
28439 8, 136, 72, 200, 40, 168, 104, 232,
28440 24, 152, 88, 216, 56, 184, 120, 248,
28441 4, 132, 68, 196, 36, 164, 100, 228,
28442 20, 148, 84, 212, 52, 180, 116, 244,
28443 12, 140, 76, 204, 44, 172, 108, 236,
28444 28, 156, 92, 220, 60, 188, 124, 252,
28445 2, 130, 66, 194, 34, 162, 98, 226,
28446 18, 146, 82, 210, 50, 178, 114, 242,
28447 10, 138, 74, 202, 42, 170, 106, 234,
28448 26, 154, 90, 218, 58, 186, 122, 250,
28449 6, 134, 70, 198, 38, 166, 102, 230,
28450 22, 150, 86, 214, 54, 182, 118, 246,
28451 14, 142, 78, 206, 46, 174, 110, 238,
28452 30, 158, 94, 222, 62, 190, 126, 254,
28453 1, 129, 65, 193, 33, 161, 97, 225,
28454 17, 145, 81, 209, 49, 177, 113, 241,
28455 9, 137, 73, 201, 41, 169, 105, 233,
28456 25, 153, 89, 217, 57, 185, 121, 249,
28457 5, 133, 69, 197, 37, 165, 101, 229,
28458 21, 149, 85, 213, 53, 181, 117, 245,
28459 13, 141, 77, 205, 45, 173, 109, 237,
28460 29, 157, 93, 221, 61, 189, 125, 253,
28461 3, 131, 67, 195, 35, 163, 99, 227,
28462 19, 147, 83, 211, 51, 179, 115, 243,
28463 11, 139, 75, 203, 43, 171, 107, 235,
28464 27, 155, 91, 219, 59, 187, 123, 251,
28465 7, 135, 71, 199, 39, 167, 103, 231,
28466 23, 151, 87, 215, 55, 183, 119, 247,
28467 15, 143, 79, 207, 47, 175, 111, 239,
28468 31, 159, 95, 223, 63, 191, 127, 255,
28469};
28470
28471static const uint32_t
28472WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
28473 1073741824, 1073742080, 1073742336, 1073742592, 1073742848, 1073743104, 1073743360, 1073743616,
28474 1073743888, 1073744400, 1073744912, 1073745424, 1073745952, 1073746976, 1073748000, 1073749024,
28475 1073750064, 1073752112, 1073754160, 1073756208, 1073758272, 1073762368, 1073766464, 1073770560,
28476 1073774672, 1073782864, 1073791056, 1073799248, 1073807104, 134217728, 134217728, 134217728,
28477};
28478
28479static const uint32_t
28480WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[32] WUFFS_BASE__POTENTIALLY_UNUSED = {
28481 1073741824, 1073742080, 1073742336, 1073742592, 1073742864, 1073743376, 1073743904, 1073744928,
28482 1073745968, 1073748016, 1073750080, 1073754176, 1073758288, 1073766480, 1073774688, 1073791072,
28483 1073807472, 1073840240, 1073873024, 1073938560, 1074004112, 1074135184, 1074266272, 1074528416,
28484 1074790576, 1075314864, 1075839168, 1076887744, 1077936336, 1080033488, 134217728, 134217728,
28485};
28486
28487#define WUFFS_DEFLATE__HUFFS_TABLE_SIZE 1024
28488
28489#define WUFFS_DEFLATE__HUFFS_TABLE_MASK 1023
28490
28491// ---------------- Private Initializer Prototypes
28492
28493// ---------------- Private Function Prototypes
28494
28495static wuffs_base__status
28496wuffs_deflate__decoder__decode_blocks(
28497 wuffs_deflate__decoder* self,
28498 wuffs_base__io_buffer* a_dst,
28499 wuffs_base__io_buffer* a_src);
28500
28501static wuffs_base__status
28502wuffs_deflate__decoder__decode_uncompressed(
28503 wuffs_deflate__decoder* self,
28504 wuffs_base__io_buffer* a_dst,
28505 wuffs_base__io_buffer* a_src);
28506
28507static wuffs_base__status
28508wuffs_deflate__decoder__init_fixed_huffman(
28509 wuffs_deflate__decoder* self);
28510
28511static wuffs_base__status
28512wuffs_deflate__decoder__init_dynamic_huffman(
28513 wuffs_deflate__decoder* self,
28514 wuffs_base__io_buffer* a_src);
28515
28516static wuffs_base__status
28517wuffs_deflate__decoder__init_huff(
28518 wuffs_deflate__decoder* self,
28519 uint32_t a_which,
28520 uint32_t a_n_codes0,
28521 uint32_t a_n_codes1,
28522 uint32_t a_base_symbol);
28523
Nigel Tao7804ffe2021-10-07 21:58:26 +110028524#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100028525static wuffs_base__status
28526wuffs_deflate__decoder__decode_huffman_bmi2(
28527 wuffs_deflate__decoder* self,
28528 wuffs_base__io_buffer* a_dst,
28529 wuffs_base__io_buffer* a_src);
Nigel Tao7804ffe2021-10-07 21:58:26 +110028530#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100028531
Nigel Taoe360a532021-04-05 22:47:03 +100028532static wuffs_base__status
28533wuffs_deflate__decoder__decode_huffman_fast32(
28534 wuffs_deflate__decoder* self,
28535 wuffs_base__io_buffer* a_dst,
28536 wuffs_base__io_buffer* a_src);
28537
28538static wuffs_base__status
28539wuffs_deflate__decoder__decode_huffman_fast64(
28540 wuffs_deflate__decoder* self,
28541 wuffs_base__io_buffer* a_dst,
28542 wuffs_base__io_buffer* a_src);
28543
28544static wuffs_base__status
Nigel Tao5571bfe2021-06-24 22:44:29 +100028545wuffs_deflate__decoder__decode_huffman_fast64__choosy_default(
28546 wuffs_deflate__decoder* self,
28547 wuffs_base__io_buffer* a_dst,
28548 wuffs_base__io_buffer* a_src);
28549
28550static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100028551wuffs_deflate__decoder__decode_huffman_slow(
28552 wuffs_deflate__decoder* self,
28553 wuffs_base__io_buffer* a_dst,
28554 wuffs_base__io_buffer* a_src);
28555
28556// ---------------- VTables
28557
28558const wuffs_base__io_transformer__func_ptrs
28559wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer = {
28560 (wuffs_base__empty_struct(*)(void*,
28561 uint32_t,
28562 bool))(&wuffs_deflate__decoder__set_quirk_enabled),
28563 (wuffs_base__status(*)(void*,
28564 wuffs_base__io_buffer*,
28565 wuffs_base__io_buffer*,
28566 wuffs_base__slice_u8))(&wuffs_deflate__decoder__transform_io),
28567 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_deflate__decoder__workbuf_len),
28568};
28569
28570// ---------------- Initializer Implementations
28571
28572wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
28573wuffs_deflate__decoder__initialize(
28574 wuffs_deflate__decoder* self,
28575 size_t sizeof_star_self,
28576 uint64_t wuffs_version,
28577 uint32_t options){
28578 if (!self) {
28579 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
28580 }
28581 if (sizeof(*self) != sizeof_star_self) {
28582 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
28583 }
28584 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
28585 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
28586 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
28587 }
28588
28589 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
28590 // The whole point of this if-check is to detect an uninitialized *self.
28591 // We disable the warning on GCC. Clang-5.0 does not have this warning.
28592#if !defined(__clang__) && defined(__GNUC__)
28593#pragma GCC diagnostic push
28594#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
28595#endif
28596 if (self->private_impl.magic != 0) {
28597 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
28598 }
28599#if !defined(__clang__) && defined(__GNUC__)
28600#pragma GCC diagnostic pop
28601#endif
28602 } else {
28603 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
28604 memset(self, 0, sizeof(*self));
28605 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
28606 } else {
28607 memset(&(self->private_impl), 0, sizeof(self->private_impl));
28608 }
28609 }
28610
Nigel Tao5571bfe2021-06-24 22:44:29 +100028611 self->private_impl.choosy_decode_huffman_fast64 = &wuffs_deflate__decoder__decode_huffman_fast64__choosy_default;
28612
Nigel Taoe360a532021-04-05 22:47:03 +100028613 self->private_impl.magic = WUFFS_BASE__MAGIC;
28614 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
28615 wuffs_base__io_transformer__vtable_name;
28616 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
28617 (const void*)(&wuffs_deflate__decoder__func_ptrs_for__wuffs_base__io_transformer);
28618 return wuffs_base__make_status(NULL);
28619}
28620
28621wuffs_deflate__decoder*
28622wuffs_deflate__decoder__alloc() {
28623 wuffs_deflate__decoder* x =
28624 (wuffs_deflate__decoder*)(calloc(sizeof(wuffs_deflate__decoder), 1));
28625 if (!x) {
28626 return NULL;
28627 }
28628 if (wuffs_deflate__decoder__initialize(
28629 x, sizeof(wuffs_deflate__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
28630 free(x);
28631 return NULL;
28632 }
28633 return x;
28634}
28635
28636size_t
28637sizeof__wuffs_deflate__decoder() {
28638 return sizeof(wuffs_deflate__decoder);
28639}
28640
28641// ---------------- Function Implementations
28642
28643// -------- func deflate.decoder.add_history
28644
28645WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
28646wuffs_deflate__decoder__add_history(
28647 wuffs_deflate__decoder* self,
28648 wuffs_base__slice_u8 a_hist) {
28649 if (!self) {
28650 return wuffs_base__make_empty_struct();
28651 }
28652 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
28653 return wuffs_base__make_empty_struct();
28654 }
28655
28656 wuffs_base__slice_u8 v_s = {0};
28657 uint64_t v_n_copied = 0;
28658 uint32_t v_already_full = 0;
28659
28660 v_s = a_hist;
28661 if (((uint64_t)(v_s.len)) >= 32768) {
28662 v_s = wuffs_base__slice_u8__suffix(v_s, 32768);
28663 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s);
28664 self->private_impl.f_history_index = 32768;
28665 } else {
Nigel Tao123a5c62022-06-03 14:17:20 +100028666 v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, (self->private_impl.f_history_index & 32767), 32768), v_s);
Nigel Taoe360a532021-04-05 22:47:03 +100028667 if (v_n_copied < ((uint64_t)(v_s.len))) {
28668 v_s = wuffs_base__slice_u8__subslice_i(v_s, v_n_copied);
28669 v_n_copied = wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8(self->private_data.f_history, 32768), v_s);
28670 self->private_impl.f_history_index = (((uint32_t)((v_n_copied & 32767))) + 32768);
28671 } else {
28672 v_already_full = 0;
28673 if (self->private_impl.f_history_index >= 32768) {
28674 v_already_full = 32768;
28675 }
28676 self->private_impl.f_history_index = ((self->private_impl.f_history_index & 32767) + ((uint32_t)((v_n_copied & 32767))) + v_already_full);
28677 }
28678 }
Nigel Tao123a5c62022-06-03 14:17:20 +100028679 wuffs_base__slice_u8__copy_from_slice(wuffs_base__make_slice_u8_ij(self->private_data.f_history, 32768, 33025), wuffs_base__make_slice_u8(self->private_data.f_history, 33025));
Nigel Taoe360a532021-04-05 22:47:03 +100028680 return wuffs_base__make_empty_struct();
28681}
28682
28683// -------- func deflate.decoder.set_quirk_enabled
28684
28685WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
28686wuffs_deflate__decoder__set_quirk_enabled(
28687 wuffs_deflate__decoder* self,
28688 uint32_t a_quirk,
28689 bool a_enabled) {
28690 return wuffs_base__make_empty_struct();
28691}
28692
28693// -------- func deflate.decoder.workbuf_len
28694
28695WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
28696wuffs_deflate__decoder__workbuf_len(
28697 const wuffs_deflate__decoder* self) {
28698 if (!self) {
28699 return wuffs_base__utility__empty_range_ii_u64();
28700 }
28701 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
28702 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
28703 return wuffs_base__utility__empty_range_ii_u64();
28704 }
28705
28706 return wuffs_base__utility__make_range_ii_u64(1, 1);
28707}
28708
28709// -------- func deflate.decoder.transform_io
28710
28711WUFFS_BASE__MAYBE_STATIC wuffs_base__status
28712wuffs_deflate__decoder__transform_io(
28713 wuffs_deflate__decoder* self,
28714 wuffs_base__io_buffer* a_dst,
28715 wuffs_base__io_buffer* a_src,
28716 wuffs_base__slice_u8 a_workbuf) {
28717 if (!self) {
28718 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
28719 }
28720 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
28721 return wuffs_base__make_status(
28722 (self->private_impl.magic == WUFFS_BASE__DISABLED)
28723 ? wuffs_base__error__disabled_by_previous_error
28724 : wuffs_base__error__initialize_not_called);
28725 }
28726 if (!a_dst || !a_src) {
28727 self->private_impl.magic = WUFFS_BASE__DISABLED;
28728 return wuffs_base__make_status(wuffs_base__error__bad_argument);
28729 }
28730 if ((self->private_impl.active_coroutine != 0) &&
28731 (self->private_impl.active_coroutine != 1)) {
28732 self->private_impl.magic = WUFFS_BASE__DISABLED;
28733 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
28734 }
28735 self->private_impl.active_coroutine = 0;
28736 wuffs_base__status status = wuffs_base__make_status(NULL);
28737
28738 uint64_t v_mark = 0;
28739 wuffs_base__status v_status = wuffs_base__make_status(NULL);
28740
28741 uint8_t* iop_a_dst = NULL;
28742 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28743 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28744 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110028745 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028746 io0_a_dst = a_dst->data.ptr;
28747 io1_a_dst = io0_a_dst + a_dst->meta.wi;
28748 iop_a_dst = io1_a_dst;
28749 io2_a_dst = io0_a_dst + a_dst->data.len;
28750 if (a_dst->meta.closed) {
28751 io2_a_dst = iop_a_dst;
28752 }
28753 }
28754
28755 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
28756 switch (coro_susp_point) {
28757 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
28758
Nigel Tao5571bfe2021-06-24 22:44:29 +100028759 self->private_impl.choosy_decode_huffman_fast64 = (
Nigel Tao7804ffe2021-10-07 21:58:26 +110028760#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100028761 wuffs_base__cpu_arch__have_x86_bmi2() ? &wuffs_deflate__decoder__decode_huffman_bmi2 :
28762#endif
28763 self->private_impl.choosy_decode_huffman_fast64);
Nigel Taoe360a532021-04-05 22:47:03 +100028764 while (true) {
28765 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
28766 {
28767 if (a_dst) {
28768 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
28769 }
28770 wuffs_base__status t_0 = wuffs_deflate__decoder__decode_blocks(self, a_dst, a_src);
28771 v_status = t_0;
28772 if (a_dst) {
28773 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
28774 }
28775 }
28776 if ( ! wuffs_base__status__is_suspension(&v_status)) {
28777 status = v_status;
28778 if (wuffs_base__status__is_error(&status)) {
28779 goto exit;
28780 } else if (wuffs_base__status__is_suspension(&status)) {
28781 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
28782 goto exit;
28783 }
28784 goto ok;
28785 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100028786 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 +100028787 wuffs_deflate__decoder__add_history(self, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst)), io0_a_dst));
28788 status = v_status;
28789 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
28790 }
28791
Nigel Taoe360a532021-04-05 22:47:03 +100028792 ok:
28793 self->private_impl.p_transform_io[0] = 0;
28794 goto exit;
28795 }
28796
28797 goto suspend;
28798 suspend:
28799 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
28800 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
28801
28802 goto exit;
28803 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110028804 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028805 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
28806 }
28807
28808 if (wuffs_base__status__is_error(&status)) {
28809 self->private_impl.magic = WUFFS_BASE__DISABLED;
28810 }
28811 return status;
28812}
28813
28814// -------- func deflate.decoder.decode_blocks
28815
28816static wuffs_base__status
28817wuffs_deflate__decoder__decode_blocks(
28818 wuffs_deflate__decoder* self,
28819 wuffs_base__io_buffer* a_dst,
28820 wuffs_base__io_buffer* a_src) {
28821 wuffs_base__status status = wuffs_base__make_status(NULL);
28822
28823 uint32_t v_final = 0;
28824 uint32_t v_b0 = 0;
28825 uint32_t v_type = 0;
28826 wuffs_base__status v_status = wuffs_base__make_status(NULL);
28827
28828 const uint8_t* iop_a_src = NULL;
28829 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28830 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28831 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110028832 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028833 io0_a_src = a_src->data.ptr;
28834 io1_a_src = io0_a_src + a_src->meta.ri;
28835 iop_a_src = io1_a_src;
28836 io2_a_src = io0_a_src + a_src->meta.wi;
28837 }
28838
28839 uint32_t coro_susp_point = self->private_impl.p_decode_blocks[0];
28840 if (coro_susp_point) {
28841 v_final = self->private_data.s_decode_blocks[0].v_final;
28842 }
28843 switch (coro_susp_point) {
28844 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
28845
28846 label__outer__continue:;
28847 while (v_final == 0) {
28848 while (self->private_impl.f_n_bits < 3) {
28849 {
28850 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
28851 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
28852 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
28853 goto suspend;
28854 }
28855 uint32_t t_0 = *iop_a_src++;
28856 v_b0 = t_0;
28857 }
28858 self->private_impl.f_bits |= (v_b0 << (self->private_impl.f_n_bits & 3));
28859 self->private_impl.f_n_bits = ((self->private_impl.f_n_bits & 3) + 8);
28860 }
28861 v_final = (self->private_impl.f_bits & 1);
28862 v_type = ((self->private_impl.f_bits >> 1) & 3);
28863 self->private_impl.f_bits >>= 3;
28864 self->private_impl.f_n_bits -= 3;
28865 if (v_type == 0) {
28866 if (a_src) {
28867 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28868 }
28869 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
28870 status = wuffs_deflate__decoder__decode_uncompressed(self, a_dst, a_src);
28871 if (a_src) {
28872 iop_a_src = a_src->data.ptr + a_src->meta.ri;
28873 }
28874 if (status.repr) {
28875 goto suspend;
28876 }
28877 goto label__outer__continue;
28878 } else if (v_type == 1) {
28879 v_status = wuffs_deflate__decoder__init_fixed_huffman(self);
28880 if ( ! wuffs_base__status__is_ok(&v_status)) {
28881 status = v_status;
28882 if (wuffs_base__status__is_error(&status)) {
28883 goto exit;
28884 } else if (wuffs_base__status__is_suspension(&status)) {
28885 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
28886 goto exit;
28887 }
28888 goto ok;
28889 }
28890 } else if (v_type == 2) {
28891 if (a_src) {
28892 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28893 }
28894 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
28895 status = wuffs_deflate__decoder__init_dynamic_huffman(self, a_src);
28896 if (a_src) {
28897 iop_a_src = a_src->data.ptr + a_src->meta.ri;
28898 }
28899 if (status.repr) {
28900 goto suspend;
28901 }
28902 } else {
28903 status = wuffs_base__make_status(wuffs_deflate__error__bad_block);
28904 goto exit;
28905 }
28906 self->private_impl.f_end_of_block = false;
28907 while (true) {
28908 if (sizeof(void*) == 4) {
28909 if (a_src) {
28910 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28911 }
28912 v_status = wuffs_deflate__decoder__decode_huffman_fast32(self, a_dst, a_src);
28913 if (a_src) {
28914 iop_a_src = a_src->data.ptr + a_src->meta.ri;
28915 }
28916 } else {
28917 if (a_src) {
28918 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28919 }
28920 v_status = wuffs_deflate__decoder__decode_huffman_fast64(self, a_dst, a_src);
28921 if (a_src) {
28922 iop_a_src = a_src->data.ptr + a_src->meta.ri;
28923 }
28924 }
28925 if (wuffs_base__status__is_error(&v_status)) {
28926 status = v_status;
28927 goto exit;
28928 }
28929 if (self->private_impl.f_end_of_block) {
28930 goto label__outer__continue;
28931 }
28932 if (a_src) {
28933 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28934 }
28935 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
28936 status = wuffs_deflate__decoder__decode_huffman_slow(self, a_dst, a_src);
28937 if (a_src) {
28938 iop_a_src = a_src->data.ptr + a_src->meta.ri;
28939 }
28940 if (status.repr) {
28941 goto suspend;
28942 }
28943 if (self->private_impl.f_end_of_block) {
28944 goto label__outer__continue;
28945 }
28946 }
28947 }
28948
Nigel Taoe360a532021-04-05 22:47:03 +100028949 ok:
28950 self->private_impl.p_decode_blocks[0] = 0;
28951 goto exit;
28952 }
28953
28954 goto suspend;
28955 suspend:
28956 self->private_impl.p_decode_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
28957 self->private_data.s_decode_blocks[0].v_final = v_final;
28958
28959 goto exit;
28960 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110028961 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028962 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
28963 }
28964
28965 return status;
28966}
28967
28968// -------- func deflate.decoder.decode_uncompressed
28969
28970static wuffs_base__status
28971wuffs_deflate__decoder__decode_uncompressed(
28972 wuffs_deflate__decoder* self,
28973 wuffs_base__io_buffer* a_dst,
28974 wuffs_base__io_buffer* a_src) {
28975 wuffs_base__status status = wuffs_base__make_status(NULL);
28976
28977 uint32_t v_length = 0;
28978 uint32_t v_n_copied = 0;
28979
28980 uint8_t* iop_a_dst = NULL;
28981 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28982 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28983 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110028984 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028985 io0_a_dst = a_dst->data.ptr;
28986 io1_a_dst = io0_a_dst + a_dst->meta.wi;
28987 iop_a_dst = io1_a_dst;
28988 io2_a_dst = io0_a_dst + a_dst->data.len;
28989 if (a_dst->meta.closed) {
28990 io2_a_dst = iop_a_dst;
28991 }
28992 }
28993 const uint8_t* iop_a_src = NULL;
28994 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28995 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
28996 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110028997 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100028998 io0_a_src = a_src->data.ptr;
28999 io1_a_src = io0_a_src + a_src->meta.ri;
29000 iop_a_src = io1_a_src;
29001 io2_a_src = io0_a_src + a_src->meta.wi;
29002 }
29003
29004 uint32_t coro_susp_point = self->private_impl.p_decode_uncompressed[0];
29005 if (coro_susp_point) {
29006 v_length = self->private_data.s_decode_uncompressed[0].v_length;
29007 }
29008 switch (coro_susp_point) {
29009 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29010
29011 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
29012 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
29013 goto exit;
29014 }
29015 self->private_impl.f_n_bits = 0;
29016 self->private_impl.f_bits = 0;
29017 {
29018 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29019 uint32_t t_0;
29020 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
29021 t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
29022 iop_a_src += 4;
29023 } else {
29024 self->private_data.s_decode_uncompressed[0].scratch = 0;
29025 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29026 while (true) {
29027 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29028 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29029 goto suspend;
29030 }
29031 uint64_t* scratch = &self->private_data.s_decode_uncompressed[0].scratch;
29032 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
29033 *scratch <<= 8;
29034 *scratch >>= 8;
29035 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
29036 if (num_bits_0 == 24) {
29037 t_0 = ((uint32_t)(*scratch));
29038 break;
29039 }
29040 num_bits_0 += 8;
29041 *scratch |= ((uint64_t)(num_bits_0)) << 56;
29042 }
29043 }
29044 v_length = t_0;
29045 }
29046 if ((((v_length) & 0xFFFF) + ((v_length) >> (32 - (16)))) != 65535) {
29047 status = wuffs_base__make_status(wuffs_deflate__error__inconsistent_stored_block_length);
29048 goto exit;
29049 }
29050 v_length = ((v_length) & 0xFFFF);
29051 while (true) {
29052 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_reader(
29053 &iop_a_dst, io2_a_dst,v_length, &iop_a_src, io2_a_src);
29054 if (v_length <= v_n_copied) {
29055 status = wuffs_base__make_status(NULL);
29056 goto ok;
29057 }
29058 v_length -= v_n_copied;
29059 if (((uint64_t)(io2_a_dst - iop_a_dst)) == 0) {
29060 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
29061 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
29062 } else {
29063 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29064 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
29065 }
29066 }
29067
Nigel Taoe360a532021-04-05 22:47:03 +100029068 ok:
29069 self->private_impl.p_decode_uncompressed[0] = 0;
29070 goto exit;
29071 }
29072
29073 goto suspend;
29074 suspend:
29075 self->private_impl.p_decode_uncompressed[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29076 self->private_data.s_decode_uncompressed[0].v_length = v_length;
29077
29078 goto exit;
29079 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110029080 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029081 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
29082 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110029083 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029084 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29085 }
29086
29087 return status;
29088}
29089
29090// -------- func deflate.decoder.init_fixed_huffman
29091
29092static wuffs_base__status
29093wuffs_deflate__decoder__init_fixed_huffman(
29094 wuffs_deflate__decoder* self) {
29095 uint32_t v_i = 0;
29096 wuffs_base__status v_status = wuffs_base__make_status(NULL);
29097
29098 while (v_i < 144) {
29099 self->private_data.f_code_lengths[v_i] = 8;
29100 v_i += 1;
29101 }
29102 while (v_i < 256) {
29103 self->private_data.f_code_lengths[v_i] = 9;
29104 v_i += 1;
29105 }
29106 while (v_i < 280) {
29107 self->private_data.f_code_lengths[v_i] = 7;
29108 v_i += 1;
29109 }
29110 while (v_i < 288) {
29111 self->private_data.f_code_lengths[v_i] = 8;
29112 v_i += 1;
29113 }
29114 while (v_i < 320) {
29115 self->private_data.f_code_lengths[v_i] = 5;
29116 v_i += 1;
29117 }
29118 v_status = wuffs_deflate__decoder__init_huff(self,
29119 0,
29120 0,
29121 288,
29122 257);
29123 if (wuffs_base__status__is_error(&v_status)) {
29124 return v_status;
29125 }
29126 v_status = wuffs_deflate__decoder__init_huff(self,
29127 1,
29128 288,
29129 320,
29130 0);
29131 if (wuffs_base__status__is_error(&v_status)) {
29132 return v_status;
29133 }
29134 return wuffs_base__make_status(NULL);
29135}
29136
29137// -------- func deflate.decoder.init_dynamic_huffman
29138
29139static wuffs_base__status
29140wuffs_deflate__decoder__init_dynamic_huffman(
29141 wuffs_deflate__decoder* self,
29142 wuffs_base__io_buffer* a_src) {
29143 wuffs_base__status status = wuffs_base__make_status(NULL);
29144
29145 uint32_t v_bits = 0;
29146 uint32_t v_n_bits = 0;
29147 uint32_t v_b0 = 0;
29148 uint32_t v_n_lit = 0;
29149 uint32_t v_n_dist = 0;
29150 uint32_t v_n_clen = 0;
29151 uint32_t v_i = 0;
29152 uint32_t v_b1 = 0;
29153 wuffs_base__status v_status = wuffs_base__make_status(NULL);
29154 uint32_t v_mask = 0;
29155 uint32_t v_table_entry = 0;
29156 uint32_t v_table_entry_n_bits = 0;
29157 uint32_t v_b2 = 0;
29158 uint32_t v_n_extra_bits = 0;
29159 uint8_t v_rep_symbol = 0;
29160 uint32_t v_rep_count = 0;
29161 uint32_t v_b3 = 0;
29162
29163 const uint8_t* iop_a_src = NULL;
29164 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29165 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29166 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110029167 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029168 io0_a_src = a_src->data.ptr;
29169 io1_a_src = io0_a_src + a_src->meta.ri;
29170 iop_a_src = io1_a_src;
29171 io2_a_src = io0_a_src + a_src->meta.wi;
29172 }
29173
29174 uint32_t coro_susp_point = self->private_impl.p_init_dynamic_huffman[0];
29175 if (coro_susp_point) {
29176 v_bits = self->private_data.s_init_dynamic_huffman[0].v_bits;
29177 v_n_bits = self->private_data.s_init_dynamic_huffman[0].v_n_bits;
29178 v_n_lit = self->private_data.s_init_dynamic_huffman[0].v_n_lit;
29179 v_n_dist = self->private_data.s_init_dynamic_huffman[0].v_n_dist;
29180 v_n_clen = self->private_data.s_init_dynamic_huffman[0].v_n_clen;
29181 v_i = self->private_data.s_init_dynamic_huffman[0].v_i;
29182 v_mask = self->private_data.s_init_dynamic_huffman[0].v_mask;
Nigel Taoe360a532021-04-05 22:47:03 +100029183 v_n_extra_bits = self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits;
29184 v_rep_symbol = self->private_data.s_init_dynamic_huffman[0].v_rep_symbol;
29185 v_rep_count = self->private_data.s_init_dynamic_huffman[0].v_rep_count;
29186 }
29187 switch (coro_susp_point) {
29188 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
29189
29190 v_bits = self->private_impl.f_bits;
29191 v_n_bits = self->private_impl.f_n_bits;
29192 while (v_n_bits < 14) {
29193 {
29194 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
29195 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29196 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29197 goto suspend;
29198 }
29199 uint32_t t_0 = *iop_a_src++;
29200 v_b0 = t_0;
29201 }
29202 v_bits |= (v_b0 << v_n_bits);
29203 v_n_bits += 8;
29204 }
29205 v_n_lit = (((v_bits) & 0x1F) + 257);
29206 if (v_n_lit > 286) {
29207 status = wuffs_base__make_status(wuffs_deflate__error__bad_literal_length_code_count);
29208 goto exit;
29209 }
29210 v_bits >>= 5;
29211 v_n_dist = (((v_bits) & 0x1F) + 1);
29212 if (v_n_dist > 30) {
29213 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance_code_count);
29214 goto exit;
29215 }
29216 v_bits >>= 5;
29217 v_n_clen = (((v_bits) & 0xF) + 4);
29218 v_bits >>= 4;
29219 v_n_bits -= 14;
29220 v_i = 0;
29221 while (v_i < v_n_clen) {
29222 while (v_n_bits < 3) {
29223 {
29224 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
29225 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29226 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29227 goto suspend;
29228 }
29229 uint32_t t_1 = *iop_a_src++;
29230 v_b1 = t_1;
29231 }
29232 v_bits |= (v_b1 << v_n_bits);
29233 v_n_bits += 8;
29234 }
29235 self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = ((uint8_t)((v_bits & 7)));
29236 v_bits >>= 3;
29237 v_n_bits -= 3;
29238 v_i += 1;
29239 }
29240 while (v_i < 19) {
29241 self->private_data.f_code_lengths[WUFFS_DEFLATE__CODE_ORDER[v_i]] = 0;
29242 v_i += 1;
29243 }
29244 v_status = wuffs_deflate__decoder__init_huff(self,
29245 0,
29246 0,
29247 19,
29248 4095);
29249 if (wuffs_base__status__is_error(&v_status)) {
29250 status = v_status;
29251 goto exit;
29252 }
29253 v_mask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
29254 v_i = 0;
29255 label__0__continue:;
29256 while (v_i < (v_n_lit + v_n_dist)) {
29257 while (true) {
29258 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_mask)];
29259 v_table_entry_n_bits = (v_table_entry & 15);
29260 if (v_n_bits >= v_table_entry_n_bits) {
29261 v_bits >>= v_table_entry_n_bits;
29262 v_n_bits -= v_table_entry_n_bits;
29263 goto label__1__break;
29264 }
29265 {
29266 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
29267 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29268 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29269 goto suspend;
29270 }
29271 uint32_t t_2 = *iop_a_src++;
29272 v_b2 = t_2;
29273 }
29274 v_bits |= (v_b2 << v_n_bits);
29275 v_n_bits += 8;
29276 }
29277 label__1__break:;
29278 if ((v_table_entry >> 24) != 128) {
29279 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29280 goto exit;
29281 }
29282 v_table_entry = ((v_table_entry >> 8) & 255);
29283 if (v_table_entry < 16) {
29284 self->private_data.f_code_lengths[v_i] = ((uint8_t)(v_table_entry));
29285 v_i += 1;
29286 goto label__0__continue;
29287 }
29288 v_n_extra_bits = 0;
29289 v_rep_symbol = 0;
29290 v_rep_count = 0;
29291 if (v_table_entry == 16) {
29292 v_n_extra_bits = 2;
29293 if (v_i <= 0) {
29294 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_repetition);
29295 goto exit;
29296 }
29297 v_rep_symbol = (self->private_data.f_code_lengths[(v_i - 1)] & 15);
29298 v_rep_count = 3;
29299 } else if (v_table_entry == 17) {
29300 v_n_extra_bits = 3;
29301 v_rep_symbol = 0;
29302 v_rep_count = 3;
29303 } else if (v_table_entry == 18) {
29304 v_n_extra_bits = 7;
29305 v_rep_symbol = 0;
29306 v_rep_count = 11;
29307 } else {
29308 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29309 goto exit;
29310 }
29311 while (v_n_bits < v_n_extra_bits) {
29312 {
29313 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
29314 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
29315 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
29316 goto suspend;
29317 }
29318 uint32_t t_3 = *iop_a_src++;
29319 v_b3 = t_3;
29320 }
29321 v_bits |= (v_b3 << v_n_bits);
29322 v_n_bits += 8;
29323 }
29324 v_rep_count += ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_n_extra_bits));
29325 v_bits >>= v_n_extra_bits;
29326 v_n_bits -= v_n_extra_bits;
29327 while (v_rep_count > 0) {
29328 if (v_i >= (v_n_lit + v_n_dist)) {
29329 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count);
29330 goto exit;
29331 }
29332 self->private_data.f_code_lengths[v_i] = v_rep_symbol;
29333 v_i += 1;
29334 v_rep_count -= 1;
29335 }
29336 }
29337 if (v_i != (v_n_lit + v_n_dist)) {
29338 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_length_count);
29339 goto exit;
29340 }
29341 if (self->private_data.f_code_lengths[256] == 0) {
29342 status = wuffs_base__make_status(wuffs_deflate__error__missing_end_of_block_code);
29343 goto exit;
29344 }
29345 v_status = wuffs_deflate__decoder__init_huff(self,
29346 0,
29347 0,
29348 v_n_lit,
29349 257);
29350 if (wuffs_base__status__is_error(&v_status)) {
29351 status = v_status;
29352 goto exit;
29353 }
29354 v_status = wuffs_deflate__decoder__init_huff(self,
29355 1,
29356 v_n_lit,
29357 (v_n_lit + v_n_dist),
29358 0);
29359 if (wuffs_base__status__is_error(&v_status)) {
29360 status = v_status;
29361 goto exit;
29362 }
29363 self->private_impl.f_bits = v_bits;
29364 self->private_impl.f_n_bits = v_n_bits;
29365
29366 goto ok;
29367 ok:
29368 self->private_impl.p_init_dynamic_huffman[0] = 0;
29369 goto exit;
29370 }
29371
29372 goto suspend;
29373 suspend:
29374 self->private_impl.p_init_dynamic_huffman[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
29375 self->private_data.s_init_dynamic_huffman[0].v_bits = v_bits;
29376 self->private_data.s_init_dynamic_huffman[0].v_n_bits = v_n_bits;
29377 self->private_data.s_init_dynamic_huffman[0].v_n_lit = v_n_lit;
29378 self->private_data.s_init_dynamic_huffman[0].v_n_dist = v_n_dist;
29379 self->private_data.s_init_dynamic_huffman[0].v_n_clen = v_n_clen;
29380 self->private_data.s_init_dynamic_huffman[0].v_i = v_i;
29381 self->private_data.s_init_dynamic_huffman[0].v_mask = v_mask;
Nigel Taoe360a532021-04-05 22:47:03 +100029382 self->private_data.s_init_dynamic_huffman[0].v_n_extra_bits = v_n_extra_bits;
29383 self->private_data.s_init_dynamic_huffman[0].v_rep_symbol = v_rep_symbol;
29384 self->private_data.s_init_dynamic_huffman[0].v_rep_count = v_rep_count;
29385
29386 goto exit;
29387 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110029388 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029389 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29390 }
29391
29392 return status;
29393}
29394
29395// -------- func deflate.decoder.init_huff
29396
29397static wuffs_base__status
29398wuffs_deflate__decoder__init_huff(
29399 wuffs_deflate__decoder* self,
29400 uint32_t a_which,
29401 uint32_t a_n_codes0,
29402 uint32_t a_n_codes1,
29403 uint32_t a_base_symbol) {
29404 uint16_t v_counts[16] = {0};
29405 uint32_t v_i = 0;
29406 uint32_t v_remaining = 0;
29407 uint16_t v_offsets[16] = {0};
29408 uint32_t v_n_symbols = 0;
29409 uint32_t v_count = 0;
29410 uint16_t v_symbols[320] = {0};
29411 uint32_t v_min_cl = 0;
29412 uint32_t v_max_cl = 0;
29413 uint32_t v_initial_high_bits = 0;
29414 uint32_t v_prev_cl = 0;
29415 uint32_t v_prev_redirect_key = 0;
29416 uint32_t v_top = 0;
29417 uint32_t v_next_top = 0;
29418 uint32_t v_code = 0;
29419 uint32_t v_key = 0;
29420 uint32_t v_value = 0;
29421 uint32_t v_cl = 0;
29422 uint32_t v_redirect_key = 0;
29423 uint32_t v_j = 0;
29424 uint32_t v_reversed_key = 0;
29425 uint32_t v_symbol = 0;
29426 uint32_t v_high_bits = 0;
29427 uint32_t v_delta = 0;
29428
29429 v_i = a_n_codes0;
29430 while (v_i < a_n_codes1) {
29431 if (v_counts[(self->private_data.f_code_lengths[v_i] & 15)] >= 320) {
29432 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29433 }
29434#if defined(__GNUC__)
29435#pragma GCC diagnostic push
29436#pragma GCC diagnostic ignored "-Wconversion"
29437#endif
29438 v_counts[(self->private_data.f_code_lengths[v_i] & 15)] += 1;
29439#if defined(__GNUC__)
29440#pragma GCC diagnostic pop
29441#endif
29442 v_i += 1;
29443 }
29444 if ((((uint32_t)(v_counts[0])) + a_n_codes0) == a_n_codes1) {
29445 return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes);
29446 }
29447 v_remaining = 1;
29448 v_i = 1;
29449 while (v_i <= 15) {
29450 if (v_remaining > 1073741824) {
29451 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29452 }
29453 v_remaining <<= 1;
29454 if (v_remaining < ((uint32_t)(v_counts[v_i]))) {
29455 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_over_subscribed);
29456 }
29457 v_remaining -= ((uint32_t)(v_counts[v_i]));
29458 v_i += 1;
29459 }
29460 if (v_remaining != 0) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110029461 if ((a_which == 1) && (v_counts[1] == 1) && ((((uint32_t)(v_counts[0])) + a_n_codes0 + 1) == a_n_codes1)) {
29462 v_i = 0;
29463 while (v_i <= 29) {
29464 if (self->private_data.f_code_lengths[(a_n_codes0 + v_i)] == 1) {
29465 self->private_impl.f_n_huffs_bits[1] = 1;
29466 self->private_data.f_huffs[1][0] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[v_i] | 1);
29467 self->private_data.f_huffs[1][1] = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[31] | 1);
29468 return wuffs_base__make_status(NULL);
29469 }
29470 v_i += 1;
29471 }
Nigel Taoe360a532021-04-05 22:47:03 +100029472 }
29473 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code_under_subscribed);
29474 }
29475 v_i = 1;
29476 while (v_i <= 15) {
29477 v_offsets[v_i] = ((uint16_t)(v_n_symbols));
29478 v_count = ((uint32_t)(v_counts[v_i]));
29479 if (v_n_symbols > (320 - v_count)) {
29480 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29481 }
29482 v_n_symbols = (v_n_symbols + v_count);
29483 v_i += 1;
29484 }
29485 if (v_n_symbols > 288) {
29486 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29487 }
29488 v_i = a_n_codes0;
29489 while (v_i < a_n_codes1) {
29490 if (v_i < a_n_codes0) {
29491 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29492 }
29493 if (self->private_data.f_code_lengths[v_i] != 0) {
29494 if (v_offsets[(self->private_data.f_code_lengths[v_i] & 15)] >= 320) {
29495 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29496 }
29497 v_symbols[v_offsets[(self->private_data.f_code_lengths[v_i] & 15)]] = ((uint16_t)((v_i - a_n_codes0)));
29498#if defined(__GNUC__)
29499#pragma GCC diagnostic push
29500#pragma GCC diagnostic ignored "-Wconversion"
29501#endif
29502 v_offsets[(self->private_data.f_code_lengths[v_i] & 15)] += 1;
29503#if defined(__GNUC__)
29504#pragma GCC diagnostic pop
29505#endif
29506 }
29507 v_i += 1;
29508 }
29509 v_min_cl = 1;
29510 while (true) {
29511 if (v_counts[v_min_cl] != 0) {
29512 goto label__0__break;
29513 }
29514 if (v_min_cl >= 9) {
29515 return wuffs_base__make_status(wuffs_deflate__error__bad_huffman_minimum_code_length);
29516 }
29517 v_min_cl += 1;
29518 }
29519 label__0__break:;
29520 v_max_cl = 15;
29521 while (true) {
29522 if (v_counts[v_max_cl] != 0) {
29523 goto label__1__break;
29524 }
29525 if (v_max_cl <= 1) {
29526 return wuffs_base__make_status(wuffs_deflate__error__no_huffman_codes);
29527 }
29528 v_max_cl -= 1;
29529 }
29530 label__1__break:;
29531 if (v_max_cl <= 9) {
29532 self->private_impl.f_n_huffs_bits[a_which] = v_max_cl;
29533 } else {
29534 self->private_impl.f_n_huffs_bits[a_which] = 9;
29535 }
29536 v_i = 0;
29537 if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) || (v_n_symbols != ((uint32_t)(v_offsets[15])))) {
29538 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29539 }
29540 if ((a_n_codes0 + ((uint32_t)(v_symbols[0]))) >= 320) {
29541 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29542 }
29543 v_initial_high_bits = 512;
29544 if (v_max_cl < 9) {
29545 v_initial_high_bits = (((uint32_t)(1)) << v_max_cl);
29546 }
29547 v_prev_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[0])))] & 15)));
29548 v_prev_redirect_key = 4294967295;
29549 v_top = 0;
29550 v_next_top = 512;
29551 v_code = 0;
29552 v_key = 0;
29553 v_value = 0;
29554 while (true) {
29555 if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320) {
29556 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29557 }
29558 v_cl = ((uint32_t)((self->private_data.f_code_lengths[(a_n_codes0 + ((uint32_t)(v_symbols[v_i])))] & 15)));
29559 if (v_cl > v_prev_cl) {
29560 v_code <<= (v_cl - v_prev_cl);
29561 if (v_code >= 32768) {
29562 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29563 }
29564 }
29565 v_prev_cl = v_cl;
29566 v_key = v_code;
29567 if (v_cl > 9) {
29568 v_cl -= 9;
29569 v_redirect_key = ((v_key >> v_cl) & 511);
29570 v_key = ((v_key) & WUFFS_BASE__LOW_BITS_MASK__U32(v_cl));
29571 if (v_prev_redirect_key != v_redirect_key) {
29572 v_prev_redirect_key = v_redirect_key;
29573 v_remaining = (((uint32_t)(1)) << v_cl);
29574 v_j = v_prev_cl;
29575 while (v_j <= 15) {
29576 if (v_remaining <= ((uint32_t)(v_counts[v_j]))) {
29577 goto label__2__break;
29578 }
29579 v_remaining -= ((uint32_t)(v_counts[v_j]));
29580 if (v_remaining > 1073741824) {
29581 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29582 }
29583 v_remaining <<= 1;
29584 v_j += 1;
29585 }
29586 label__2__break:;
29587 if ((v_j <= 9) || (15 < v_j)) {
29588 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29589 }
29590 v_j -= 9;
29591 v_initial_high_bits = (((uint32_t)(1)) << v_j);
29592 v_top = v_next_top;
29593 if ((v_top + (((uint32_t)(1)) << v_j)) > 1024) {
29594 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29595 }
29596 v_next_top = (v_top + (((uint32_t)(1)) << v_j));
29597 v_redirect_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_redirect_key >> 1)])) | ((v_redirect_key & 1) << 8));
29598 self->private_data.f_huffs[a_which][v_redirect_key] = (268435465 | (v_top << 8) | (v_j << 4));
29599 }
29600 }
29601 if ((v_key >= 512) || (v_counts[v_prev_cl] <= 0)) {
29602 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29603 }
29604#if defined(__GNUC__)
29605#pragma GCC diagnostic push
29606#pragma GCC diagnostic ignored "-Wconversion"
29607#endif
29608 v_counts[v_prev_cl] -= 1;
29609#if defined(__GNUC__)
29610#pragma GCC diagnostic pop
29611#endif
29612 v_reversed_key = (((uint32_t)(WUFFS_DEFLATE__REVERSE8[(v_key >> 1)])) | ((v_key & 1) << 8));
29613 v_reversed_key >>= (9 - v_cl);
29614 v_symbol = ((uint32_t)(v_symbols[v_i]));
29615 if (v_symbol == 256) {
29616 v_value = (536870912 | v_cl);
29617 } else if ((v_symbol < 256) && (a_which == 0)) {
29618 v_value = (2147483648 | (v_symbol << 8) | v_cl);
29619 } else if (v_symbol >= a_base_symbol) {
29620 v_symbol -= a_base_symbol;
29621 if (a_which == 0) {
29622 v_value = (WUFFS_DEFLATE__LCODE_MAGIC_NUMBERS[(v_symbol & 31)] | v_cl);
29623 } else {
29624 v_value = (WUFFS_DEFLATE__DCODE_MAGIC_NUMBERS[(v_symbol & 31)] | v_cl);
29625 }
29626 } else {
29627 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29628 }
29629 v_high_bits = v_initial_high_bits;
29630 v_delta = (((uint32_t)(1)) << v_cl);
29631 while (v_high_bits >= v_delta) {
29632 v_high_bits -= v_delta;
29633 if ((v_top + ((v_high_bits | v_reversed_key) & 511)) >= 1024) {
29634 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29635 }
29636 self->private_data.f_huffs[a_which][(v_top + ((v_high_bits | v_reversed_key) & 511))] = v_value;
29637 }
29638 v_i += 1;
29639 if (v_i >= v_n_symbols) {
29640 goto label__3__break;
29641 }
29642 v_code += 1;
29643 if (v_code >= 32768) {
29644 return wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29645 }
29646 }
29647 label__3__break:;
29648 return wuffs_base__make_status(NULL);
29649}
29650
Nigel Tao5571bfe2021-06-24 22:44:29 +100029651// ‼ WUFFS MULTI-FILE SECTION +x86_bmi2
29652// -------- func deflate.decoder.decode_huffman_bmi2
29653
Nigel Tao7804ffe2021-10-07 21:58:26 +110029654#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100029655WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("bmi2")
29656static wuffs_base__status
29657wuffs_deflate__decoder__decode_huffman_bmi2(
29658 wuffs_deflate__decoder* self,
29659 wuffs_base__io_buffer* a_dst,
29660 wuffs_base__io_buffer* a_src) {
29661 wuffs_base__status status = wuffs_base__make_status(NULL);
29662
29663 uint64_t v_bits = 0;
29664 uint32_t v_n_bits = 0;
29665 uint32_t v_table_entry = 0;
29666 uint32_t v_table_entry_n_bits = 0;
29667 uint64_t v_lmask = 0;
29668 uint64_t v_dmask = 0;
29669 uint32_t v_redir_top = 0;
29670 uint32_t v_redir_mask = 0;
29671 uint32_t v_length = 0;
29672 uint32_t v_dist_minus_1 = 0;
29673 uint32_t v_hlen = 0;
29674 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029675 uint32_t v_hdist_adjustment = 0;
Nigel Tao5571bfe2021-06-24 22:44:29 +100029676
29677 uint8_t* iop_a_dst = NULL;
29678 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29679 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29680 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110029681 if (a_dst && a_dst->data.ptr) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100029682 io0_a_dst = a_dst->data.ptr;
29683 io1_a_dst = io0_a_dst + a_dst->meta.wi;
29684 iop_a_dst = io1_a_dst;
29685 io2_a_dst = io0_a_dst + a_dst->data.len;
29686 if (a_dst->meta.closed) {
29687 io2_a_dst = iop_a_dst;
29688 }
29689 }
29690 const uint8_t* iop_a_src = NULL;
29691 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29692 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29693 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110029694 if (a_src && a_src->data.ptr) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100029695 io0_a_src = a_src->data.ptr;
29696 io1_a_src = io0_a_src + a_src->meta.ri;
29697 iop_a_src = io1_a_src;
29698 io2_a_src = io0_a_src + a_src->meta.wi;
29699 }
29700
29701 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
29702 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
29703 goto exit;
29704 }
29705 v_bits = ((uint64_t)(self->private_impl.f_bits));
29706 v_n_bits = self->private_impl.f_n_bits;
29707 v_lmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
29708 v_dmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029709 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
29710 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
29711 goto exit;
29712 }
29713 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 +100029714 label__loop__continue:;
29715 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8)) {
29716 v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63)));
29717 iop_a_src += ((63 - (v_n_bits & 63)) >> 3);
29718 v_n_bits |= 56;
29719 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
29720 v_table_entry_n_bits = (v_table_entry & 15);
29721 v_bits >>= v_table_entry_n_bits;
29722 v_n_bits -= v_table_entry_n_bits;
29723 if ((v_table_entry >> 31) != 0) {
29724 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
29725 goto label__loop__continue;
29726 } else if ((v_table_entry >> 30) != 0) {
29727 } else if ((v_table_entry >> 29) != 0) {
29728 self->private_impl.f_end_of_block = true;
29729 goto label__loop__break;
29730 } else if ((v_table_entry >> 28) != 0) {
29731 v_redir_top = ((v_table_entry >> 8) & 65535);
29732 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
29733 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
29734 v_table_entry_n_bits = (v_table_entry & 15);
29735 v_bits >>= v_table_entry_n_bits;
29736 v_n_bits -= v_table_entry_n_bits;
29737 if ((v_table_entry >> 31) != 0) {
29738 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
29739 goto label__loop__continue;
29740 } else if ((v_table_entry >> 30) != 0) {
29741 } else if ((v_table_entry >> 29) != 0) {
29742 self->private_impl.f_end_of_block = true;
29743 goto label__loop__break;
29744 } else if ((v_table_entry >> 28) != 0) {
29745 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29746 goto exit;
29747 } else if ((v_table_entry >> 27) != 0) {
29748 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
29749 goto exit;
29750 } else {
29751 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29752 goto exit;
29753 }
29754 } else if ((v_table_entry >> 27) != 0) {
29755 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
29756 goto exit;
29757 } else {
29758 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29759 goto exit;
29760 }
29761 v_length = (((v_table_entry >> 8) & 255) + 3);
29762 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
29763 if (v_table_entry_n_bits > 0) {
29764 v_length = (((v_length + 253 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255) + 3);
29765 v_bits >>= v_table_entry_n_bits;
29766 v_n_bits -= v_table_entry_n_bits;
29767 }
29768 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
29769 v_table_entry_n_bits = (v_table_entry & 15);
29770 v_bits >>= v_table_entry_n_bits;
29771 v_n_bits -= v_table_entry_n_bits;
29772 if ((v_table_entry >> 28) == 1) {
29773 v_redir_top = ((v_table_entry >> 8) & 65535);
29774 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
29775 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
29776 v_table_entry_n_bits = (v_table_entry & 15);
29777 v_bits >>= v_table_entry_n_bits;
29778 v_n_bits -= v_table_entry_n_bits;
29779 }
29780 if ((v_table_entry >> 24) != 64) {
29781 if ((v_table_entry >> 24) == 8) {
29782 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
29783 goto exit;
29784 }
29785 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29786 goto exit;
29787 }
29788 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
29789 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
29790 v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767);
29791 v_bits >>= v_table_entry_n_bits;
29792 v_n_bits -= v_table_entry_n_bits;
29793 while (true) {
29794 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
29795 v_hlen = 0;
29796 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
29797 if (v_length > v_hdist) {
29798 v_length -= v_hdist;
29799 v_hlen = v_hdist;
29800 } else {
29801 v_hlen = v_length;
29802 v_length = 0;
29803 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029804 v_hdist += v_hdist_adjustment;
Nigel Tao5571bfe2021-06-24 22:44:29 +100029805 if (self->private_impl.f_history_index < v_hdist) {
29806 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
29807 goto exit;
29808 }
Nigel Tao5571bfe2021-06-24 22:44:29 +100029809 wuffs_base__io_writer__limited_copy_u32_from_slice(
Nigel Tao123a5c62022-06-03 14:17:20 +100029810 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767), 33025));
Nigel Tao5571bfe2021-06-24 22:44:29 +100029811 if (v_length == 0) {
29812 goto label__loop__continue;
29813 }
29814 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)))) {
29815 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
29816 goto exit;
29817 }
29818 }
29819 if ((v_dist_minus_1 + 1) >= 8) {
29820 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
29821 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
29822 } else if ((v_dist_minus_1 + 1) == 1) {
29823 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
29824 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
29825 } else {
29826 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
29827 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
29828 }
29829 goto label__0__break;
29830 }
29831 label__0__break:;
29832 }
29833 label__loop__break:;
29834 if (v_n_bits > 63) {
29835 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
29836 goto exit;
29837 }
29838 while (v_n_bits >= 8) {
29839 v_n_bits -= 8;
29840 if (iop_a_src > io1_a_src) {
29841 iop_a_src--;
29842 } else {
29843 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
29844 goto exit;
29845 }
29846 }
29847 self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1)) << v_n_bits) - 1))));
29848 self->private_impl.f_n_bits = v_n_bits;
29849 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
29850 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
29851 goto exit;
29852 }
29853 goto exit;
29854 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110029855 if (a_dst && a_dst->data.ptr) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100029856 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
29857 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110029858 if (a_src && a_src->data.ptr) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100029859 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
29860 }
29861
29862 return status;
29863}
Nigel Tao7804ffe2021-10-07 21:58:26 +110029864#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Tao5571bfe2021-06-24 22:44:29 +100029865// ‼ WUFFS MULTI-FILE SECTION -x86_bmi2
29866
Nigel Taoe360a532021-04-05 22:47:03 +100029867// -------- func deflate.decoder.decode_huffman_fast32
29868
29869static wuffs_base__status
29870wuffs_deflate__decoder__decode_huffman_fast32(
29871 wuffs_deflate__decoder* self,
29872 wuffs_base__io_buffer* a_dst,
29873 wuffs_base__io_buffer* a_src) {
29874 wuffs_base__status status = wuffs_base__make_status(NULL);
29875
29876 uint32_t v_bits = 0;
29877 uint32_t v_n_bits = 0;
29878 uint32_t v_table_entry = 0;
29879 uint32_t v_table_entry_n_bits = 0;
29880 uint32_t v_lmask = 0;
29881 uint32_t v_dmask = 0;
29882 uint32_t v_redir_top = 0;
29883 uint32_t v_redir_mask = 0;
29884 uint32_t v_length = 0;
29885 uint32_t v_dist_minus_1 = 0;
29886 uint32_t v_hlen = 0;
29887 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029888 uint32_t v_hdist_adjustment = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100029889
29890 uint8_t* iop_a_dst = NULL;
29891 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29892 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29893 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110029894 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029895 io0_a_dst = a_dst->data.ptr;
29896 io1_a_dst = io0_a_dst + a_dst->meta.wi;
29897 iop_a_dst = io1_a_dst;
29898 io2_a_dst = io0_a_dst + a_dst->data.len;
29899 if (a_dst->meta.closed) {
29900 io2_a_dst = iop_a_dst;
29901 }
29902 }
29903 const uint8_t* iop_a_src = NULL;
29904 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29905 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
29906 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110029907 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100029908 io0_a_src = a_src->data.ptr;
29909 io1_a_src = io0_a_src + a_src->meta.ri;
29910 iop_a_src = io1_a_src;
29911 io2_a_src = io0_a_src + a_src->meta.wi;
29912 }
29913
29914 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
29915 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
29916 goto exit;
29917 }
29918 v_bits = self->private_impl.f_bits;
29919 v_n_bits = self->private_impl.f_n_bits;
29920 v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
29921 v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100029922 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
29923 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
29924 goto exit;
29925 }
29926 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 +100029927 label__loop__continue:;
29928 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 12)) {
29929 if (v_n_bits < 15) {
29930 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29931 iop_a_src += 1;
29932 v_n_bits += 8;
29933 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29934 iop_a_src += 1;
29935 v_n_bits += 8;
29936 } else {
29937 }
29938 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
29939 v_table_entry_n_bits = (v_table_entry & 15);
29940 v_bits >>= v_table_entry_n_bits;
29941 v_n_bits -= v_table_entry_n_bits;
29942 if ((v_table_entry >> 31) != 0) {
29943 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
29944 goto label__loop__continue;
29945 } else if ((v_table_entry >> 30) != 0) {
29946 } else if ((v_table_entry >> 29) != 0) {
29947 self->private_impl.f_end_of_block = true;
29948 goto label__loop__break;
29949 } else if ((v_table_entry >> 28) != 0) {
29950 if (v_n_bits < 15) {
29951 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29952 iop_a_src += 1;
29953 v_n_bits += 8;
29954 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29955 iop_a_src += 1;
29956 v_n_bits += 8;
29957 } else {
29958 }
29959 v_redir_top = ((v_table_entry >> 8) & 65535);
29960 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
29961 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
29962 v_table_entry_n_bits = (v_table_entry & 15);
29963 v_bits >>= v_table_entry_n_bits;
29964 v_n_bits -= v_table_entry_n_bits;
29965 if ((v_table_entry >> 31) != 0) {
29966 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
29967 goto label__loop__continue;
29968 } else if ((v_table_entry >> 30) != 0) {
29969 } else if ((v_table_entry >> 29) != 0) {
29970 self->private_impl.f_end_of_block = true;
29971 goto label__loop__break;
29972 } else if ((v_table_entry >> 28) != 0) {
29973 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29974 goto exit;
29975 } else if ((v_table_entry >> 27) != 0) {
29976 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
29977 goto exit;
29978 } else {
29979 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29980 goto exit;
29981 }
29982 } else if ((v_table_entry >> 27) != 0) {
29983 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
29984 goto exit;
29985 } else {
29986 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
29987 goto exit;
29988 }
29989 v_length = (((v_table_entry >> 8) & 255) + 3);
29990 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
29991 if (v_table_entry_n_bits > 0) {
29992 if (v_n_bits < 15) {
29993 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29994 iop_a_src += 1;
29995 v_n_bits += 8;
29996 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
29997 iop_a_src += 1;
29998 v_n_bits += 8;
29999 } else {
30000 }
30001 v_length = (((v_length + 253 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255) + 3);
30002 v_bits >>= v_table_entry_n_bits;
30003 v_n_bits -= v_table_entry_n_bits;
30004 } else {
30005 }
30006 if (v_n_bits < 15) {
30007 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30008 iop_a_src += 1;
30009 v_n_bits += 8;
30010 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30011 iop_a_src += 1;
30012 v_n_bits += 8;
30013 } else {
30014 }
30015 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
30016 v_table_entry_n_bits = (v_table_entry & 15);
30017 v_bits >>= v_table_entry_n_bits;
30018 v_n_bits -= v_table_entry_n_bits;
30019 if ((v_table_entry >> 28) == 1) {
30020 if (v_n_bits < 15) {
30021 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30022 iop_a_src += 1;
30023 v_n_bits += 8;
30024 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30025 iop_a_src += 1;
30026 v_n_bits += 8;
30027 } else {
30028 }
30029 v_redir_top = ((v_table_entry >> 8) & 65535);
30030 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
30031 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
30032 v_table_entry_n_bits = (v_table_entry & 15);
30033 v_bits >>= v_table_entry_n_bits;
30034 v_n_bits -= v_table_entry_n_bits;
30035 } else {
30036 }
30037 if ((v_table_entry >> 24) != 64) {
30038 if ((v_table_entry >> 24) == 8) {
30039 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30040 goto exit;
30041 }
30042 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30043 goto exit;
30044 }
30045 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
30046 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
30047 if (v_n_bits < v_table_entry_n_bits) {
30048 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30049 iop_a_src += 1;
30050 v_n_bits += 8;
30051 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30052 iop_a_src += 1;
30053 v_n_bits += 8;
30054 }
30055 v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767);
30056 v_bits >>= v_table_entry_n_bits;
30057 v_n_bits -= v_table_entry_n_bits;
30058 while (true) {
30059 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
30060 v_hlen = 0;
30061 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
30062 if (v_length > v_hdist) {
30063 v_length -= v_hdist;
30064 v_hlen = v_hdist;
30065 } else {
30066 v_hlen = v_length;
30067 v_length = 0;
30068 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030069 v_hdist += v_hdist_adjustment;
Nigel Taoe360a532021-04-05 22:47:03 +100030070 if (self->private_impl.f_history_index < v_hdist) {
30071 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
30072 goto exit;
30073 }
Nigel Taoe360a532021-04-05 22:47:03 +100030074 wuffs_base__io_writer__limited_copy_u32_from_slice(
Nigel Tao123a5c62022-06-03 14:17:20 +100030075 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767), 33025));
Nigel Taoe360a532021-04-05 22:47:03 +100030076 if (v_length == 0) {
30077 goto label__loop__continue;
30078 }
30079 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)))) {
30080 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
30081 goto exit;
30082 }
30083 }
30084 if ((v_dist_minus_1 + 1) >= 8) {
30085 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
30086 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
30087 } else {
30088 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
30089 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
30090 }
30091 goto label__0__break;
30092 }
30093 label__0__break:;
30094 }
30095 label__loop__break:;
30096 while (v_n_bits >= 8) {
30097 v_n_bits -= 8;
30098 if (iop_a_src > io1_a_src) {
30099 iop_a_src--;
30100 } else {
30101 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
30102 goto exit;
30103 }
30104 }
30105 self->private_impl.f_bits = (v_bits & ((((uint32_t)(1)) << v_n_bits) - 1));
30106 self->private_impl.f_n_bits = v_n_bits;
30107 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
30108 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30109 goto exit;
30110 }
30111 goto exit;
30112 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110030113 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030114 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
30115 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110030116 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030117 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30118 }
30119
30120 return status;
30121}
30122
30123// -------- func deflate.decoder.decode_huffman_fast64
30124
30125static wuffs_base__status
30126wuffs_deflate__decoder__decode_huffman_fast64(
30127 wuffs_deflate__decoder* self,
30128 wuffs_base__io_buffer* a_dst,
30129 wuffs_base__io_buffer* a_src) {
Nigel Tao5571bfe2021-06-24 22:44:29 +100030130 return (*self->private_impl.choosy_decode_huffman_fast64)(self, a_dst, a_src);
30131}
30132
30133static wuffs_base__status
30134wuffs_deflate__decoder__decode_huffman_fast64__choosy_default(
30135 wuffs_deflate__decoder* self,
30136 wuffs_base__io_buffer* a_dst,
30137 wuffs_base__io_buffer* a_src) {
Nigel Taoe360a532021-04-05 22:47:03 +100030138 wuffs_base__status status = wuffs_base__make_status(NULL);
30139
30140 uint64_t v_bits = 0;
30141 uint32_t v_n_bits = 0;
30142 uint32_t v_table_entry = 0;
30143 uint32_t v_table_entry_n_bits = 0;
30144 uint64_t v_lmask = 0;
30145 uint64_t v_dmask = 0;
30146 uint32_t v_redir_top = 0;
30147 uint32_t v_redir_mask = 0;
30148 uint32_t v_length = 0;
30149 uint32_t v_dist_minus_1 = 0;
30150 uint32_t v_hlen = 0;
30151 uint32_t v_hdist = 0;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030152 uint32_t v_hdist_adjustment = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100030153
30154 uint8_t* iop_a_dst = NULL;
30155 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30156 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30157 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110030158 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030159 io0_a_dst = a_dst->data.ptr;
30160 io1_a_dst = io0_a_dst + a_dst->meta.wi;
30161 iop_a_dst = io1_a_dst;
30162 io2_a_dst = io0_a_dst + a_dst->data.len;
30163 if (a_dst->meta.closed) {
30164 io2_a_dst = iop_a_dst;
30165 }
30166 }
30167 const uint8_t* iop_a_src = NULL;
30168 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30169 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30170 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110030171 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030172 io0_a_src = a_src->data.ptr;
30173 io1_a_src = io0_a_src + a_src->meta.ri;
30174 iop_a_src = io1_a_src;
30175 io2_a_src = io0_a_src + a_src->meta.wi;
30176 }
30177
30178 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
30179 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30180 goto exit;
30181 }
30182 v_bits = ((uint64_t)(self->private_impl.f_bits));
30183 v_n_bits = self->private_impl.f_n_bits;
30184 v_lmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
30185 v_dmask = ((((uint64_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030186 if (self->private_impl.f_transformed_history_count < (a_dst ? a_dst->meta.pos : 0)) {
30187 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
30188 goto exit;
30189 }
30190 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 +100030191 label__loop__continue:;
30192 while ((((uint64_t)(io2_a_dst - iop_a_dst)) >= 266) && (((uint64_t)(io2_a_src - iop_a_src)) >= 8)) {
30193 v_bits |= ((uint64_t)(wuffs_base__peek_u64le__no_bounds_check(iop_a_src) << (v_n_bits & 63)));
30194 iop_a_src += ((63 - (v_n_bits & 63)) >> 3);
30195 v_n_bits |= 56;
30196 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
30197 v_table_entry_n_bits = (v_table_entry & 15);
30198 v_bits >>= v_table_entry_n_bits;
30199 v_n_bits -= v_table_entry_n_bits;
30200 if ((v_table_entry >> 31) != 0) {
30201 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
30202 goto label__loop__continue;
30203 } else if ((v_table_entry >> 30) != 0) {
30204 } else if ((v_table_entry >> 29) != 0) {
30205 self->private_impl.f_end_of_block = true;
30206 goto label__loop__break;
30207 } else if ((v_table_entry >> 28) != 0) {
30208 v_redir_top = ((v_table_entry >> 8) & 65535);
30209 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
30210 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
30211 v_table_entry_n_bits = (v_table_entry & 15);
30212 v_bits >>= v_table_entry_n_bits;
30213 v_n_bits -= v_table_entry_n_bits;
30214 if ((v_table_entry >> 31) != 0) {
30215 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(((v_table_entry >> 8) & 255)))), iop_a_dst += 1);
30216 goto label__loop__continue;
30217 } else if ((v_table_entry >> 30) != 0) {
30218 } else if ((v_table_entry >> 29) != 0) {
30219 self->private_impl.f_end_of_block = true;
30220 goto label__loop__break;
30221 } else if ((v_table_entry >> 28) != 0) {
30222 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30223 goto exit;
30224 } else if ((v_table_entry >> 27) != 0) {
30225 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30226 goto exit;
30227 } else {
30228 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30229 goto exit;
30230 }
30231 } else if ((v_table_entry >> 27) != 0) {
30232 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30233 goto exit;
30234 } else {
30235 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30236 goto exit;
30237 }
30238 v_length = (((v_table_entry >> 8) & 255) + 3);
30239 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
30240 if (v_table_entry_n_bits > 0) {
30241 v_length = (((v_length + 253 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 255) + 3);
30242 v_bits >>= v_table_entry_n_bits;
30243 v_n_bits -= v_table_entry_n_bits;
30244 }
30245 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
30246 v_table_entry_n_bits = (v_table_entry & 15);
30247 v_bits >>= v_table_entry_n_bits;
30248 v_n_bits -= v_table_entry_n_bits;
30249 if ((v_table_entry >> 28) == 1) {
30250 v_redir_top = ((v_table_entry >> 8) & 65535);
30251 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
30252 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (((uint32_t)((v_bits & 4294967295))) & v_redir_mask)) & 1023)];
30253 v_table_entry_n_bits = (v_table_entry & 15);
30254 v_bits >>= v_table_entry_n_bits;
30255 v_n_bits -= v_table_entry_n_bits;
30256 }
30257 if ((v_table_entry >> 24) != 64) {
30258 if ((v_table_entry >> 24) == 8) {
30259 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30260 goto exit;
30261 }
30262 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30263 goto exit;
30264 }
30265 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
30266 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
30267 v_dist_minus_1 = ((v_dist_minus_1 + ((uint32_t)(((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U64(v_table_entry_n_bits))))) & 32767);
30268 v_bits >>= v_table_entry_n_bits;
30269 v_n_bits -= v_table_entry_n_bits;
30270 while (true) {
30271 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
30272 v_hlen = 0;
30273 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
30274 if (v_length > v_hdist) {
30275 v_length -= v_hdist;
30276 v_hlen = v_hdist;
30277 } else {
30278 v_hlen = v_length;
30279 v_length = 0;
30280 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030281 v_hdist += v_hdist_adjustment;
Nigel Taoe360a532021-04-05 22:47:03 +100030282 if (self->private_impl.f_history_index < v_hdist) {
30283 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
30284 goto exit;
30285 }
Nigel Taoe360a532021-04-05 22:47:03 +100030286 wuffs_base__io_writer__limited_copy_u32_from_slice(
Nigel Tao123a5c62022-06-03 14:17:20 +100030287 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767), 33025));
Nigel Taoe360a532021-04-05 22:47:03 +100030288 if (v_length == 0) {
30289 goto label__loop__continue;
30290 }
30291 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)))) {
30292 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_distance);
30293 goto exit;
30294 }
30295 }
30296 if ((v_dist_minus_1 + 1) >= 8) {
30297 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_fast(
30298 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
Nigel Tao5571bfe2021-06-24 22:44:29 +100030299 } else if ((v_dist_minus_1 + 1) == 1) {
30300 wuffs_base__io_writer__limited_copy_u32_from_history_8_byte_chunks_distance_1_fast(
30301 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
Nigel Taoe360a532021-04-05 22:47:03 +100030302 } else {
30303 wuffs_base__io_writer__limited_copy_u32_from_history_fast(
30304 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
30305 }
30306 goto label__0__break;
30307 }
30308 label__0__break:;
30309 }
30310 label__loop__break:;
30311 if (v_n_bits > 63) {
30312 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30313 goto exit;
30314 }
30315 while (v_n_bits >= 8) {
30316 v_n_bits -= 8;
30317 if (iop_a_src > io1_a_src) {
30318 iop_a_src--;
30319 } else {
30320 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_i_o);
30321 goto exit;
30322 }
30323 }
30324 self->private_impl.f_bits = ((uint32_t)((v_bits & ((((uint64_t)(1)) << v_n_bits) - 1))));
30325 self->private_impl.f_n_bits = v_n_bits;
30326 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> self->private_impl.f_n_bits) != 0)) {
30327 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30328 goto exit;
30329 }
30330 goto exit;
30331 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110030332 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030333 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
30334 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110030335 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030336 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30337 }
30338
30339 return status;
30340}
30341
30342// -------- func deflate.decoder.decode_huffman_slow
30343
30344static wuffs_base__status
30345wuffs_deflate__decoder__decode_huffman_slow(
30346 wuffs_deflate__decoder* self,
30347 wuffs_base__io_buffer* a_dst,
30348 wuffs_base__io_buffer* a_src) {
30349 wuffs_base__status status = wuffs_base__make_status(NULL);
30350
30351 uint32_t v_bits = 0;
30352 uint32_t v_n_bits = 0;
30353 uint32_t v_table_entry = 0;
30354 uint32_t v_table_entry_n_bits = 0;
30355 uint32_t v_lmask = 0;
30356 uint32_t v_dmask = 0;
30357 uint32_t v_b0 = 0;
30358 uint32_t v_redir_top = 0;
30359 uint32_t v_redir_mask = 0;
30360 uint32_t v_b1 = 0;
30361 uint32_t v_length = 0;
30362 uint32_t v_b2 = 0;
30363 uint32_t v_b3 = 0;
30364 uint32_t v_b4 = 0;
30365 uint32_t v_dist_minus_1 = 0;
30366 uint32_t v_b5 = 0;
30367 uint32_t v_n_copied = 0;
30368 uint32_t v_hlen = 0;
30369 uint32_t v_hdist = 0;
30370
30371 uint8_t* iop_a_dst = NULL;
30372 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30373 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30374 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110030375 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030376 io0_a_dst = a_dst->data.ptr;
30377 io1_a_dst = io0_a_dst + a_dst->meta.wi;
30378 iop_a_dst = io1_a_dst;
30379 io2_a_dst = io0_a_dst + a_dst->data.len;
30380 if (a_dst->meta.closed) {
30381 io2_a_dst = iop_a_dst;
30382 }
30383 }
30384 const uint8_t* iop_a_src = NULL;
30385 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30386 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30387 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110030388 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030389 io0_a_src = a_src->data.ptr;
30390 io1_a_src = io0_a_src + a_src->meta.ri;
30391 iop_a_src = io1_a_src;
30392 io2_a_src = io0_a_src + a_src->meta.wi;
30393 }
30394
30395 uint32_t coro_susp_point = self->private_impl.p_decode_huffman_slow[0];
30396 if (coro_susp_point) {
30397 v_bits = self->private_data.s_decode_huffman_slow[0].v_bits;
30398 v_n_bits = self->private_data.s_decode_huffman_slow[0].v_n_bits;
Nigel Taoe360a532021-04-05 22:47:03 +100030399 v_table_entry_n_bits = self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits;
30400 v_lmask = self->private_data.s_decode_huffman_slow[0].v_lmask;
30401 v_dmask = self->private_data.s_decode_huffman_slow[0].v_dmask;
30402 v_redir_top = self->private_data.s_decode_huffman_slow[0].v_redir_top;
30403 v_redir_mask = self->private_data.s_decode_huffman_slow[0].v_redir_mask;
30404 v_length = self->private_data.s_decode_huffman_slow[0].v_length;
30405 v_dist_minus_1 = self->private_data.s_decode_huffman_slow[0].v_dist_minus_1;
Nigel Taoe360a532021-04-05 22:47:03 +100030406 }
30407 switch (coro_susp_point) {
30408 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30409
30410 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
30411 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30412 goto exit;
30413 }
30414 v_bits = self->private_impl.f_bits;
30415 v_n_bits = self->private_impl.f_n_bits;
30416 v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1);
30417 v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1);
30418 label__loop__continue:;
30419 while ( ! (self->private_impl.p_decode_huffman_slow[0] != 0)) {
30420 while (true) {
30421 v_table_entry = self->private_data.f_huffs[0][(v_bits & v_lmask)];
30422 v_table_entry_n_bits = (v_table_entry & 15);
30423 if (v_n_bits >= v_table_entry_n_bits) {
30424 v_bits >>= v_table_entry_n_bits;
30425 v_n_bits -= v_table_entry_n_bits;
30426 goto label__0__break;
30427 }
30428 {
30429 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30430 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30431 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30432 goto suspend;
30433 }
30434 uint32_t t_0 = *iop_a_src++;
30435 v_b0 = t_0;
30436 }
30437 v_bits |= (v_b0 << v_n_bits);
30438 v_n_bits += 8;
30439 }
30440 label__0__break:;
30441 if ((v_table_entry >> 31) != 0) {
30442 self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)(((v_table_entry >> 8) & 255)));
30443 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
30444 if (iop_a_dst == io2_a_dst) {
30445 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
30446 goto suspend;
30447 }
30448 *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch));
30449 goto label__loop__continue;
30450 } else if ((v_table_entry >> 30) != 0) {
30451 } else if ((v_table_entry >> 29) != 0) {
30452 self->private_impl.f_end_of_block = true;
30453 goto label__loop__break;
30454 } else if ((v_table_entry >> 28) != 0) {
30455 v_redir_top = ((v_table_entry >> 8) & 65535);
30456 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
30457 while (true) {
30458 v_table_entry = self->private_data.f_huffs[0][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
30459 v_table_entry_n_bits = (v_table_entry & 15);
30460 if (v_n_bits >= v_table_entry_n_bits) {
30461 v_bits >>= v_table_entry_n_bits;
30462 v_n_bits -= v_table_entry_n_bits;
30463 goto label__1__break;
30464 }
30465 {
30466 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
30467 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30468 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30469 goto suspend;
30470 }
30471 uint32_t t_1 = *iop_a_src++;
30472 v_b1 = t_1;
30473 }
30474 v_bits |= (v_b1 << v_n_bits);
30475 v_n_bits += 8;
30476 }
30477 label__1__break:;
30478 if ((v_table_entry >> 31) != 0) {
30479 self->private_data.s_decode_huffman_slow[0].scratch = ((uint8_t)(((v_table_entry >> 8) & 255)));
30480 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
30481 if (iop_a_dst == io2_a_dst) {
30482 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
30483 goto suspend;
30484 }
30485 *iop_a_dst++ = ((uint8_t)(self->private_data.s_decode_huffman_slow[0].scratch));
30486 goto label__loop__continue;
30487 } else if ((v_table_entry >> 30) != 0) {
30488 } else if ((v_table_entry >> 29) != 0) {
30489 self->private_impl.f_end_of_block = true;
30490 goto label__loop__break;
30491 } else if ((v_table_entry >> 28) != 0) {
30492 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30493 goto exit;
30494 } else if ((v_table_entry >> 27) != 0) {
30495 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30496 goto exit;
30497 } else {
30498 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30499 goto exit;
30500 }
30501 } else if ((v_table_entry >> 27) != 0) {
30502 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30503 goto exit;
30504 } else {
30505 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30506 goto exit;
30507 }
30508 v_length = (((v_table_entry >> 8) & 255) + 3);
30509 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
30510 if (v_table_entry_n_bits > 0) {
30511 while (v_n_bits < v_table_entry_n_bits) {
30512 {
30513 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
30514 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30515 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30516 goto suspend;
30517 }
30518 uint32_t t_2 = *iop_a_src++;
30519 v_b2 = t_2;
30520 }
30521 v_bits |= (v_b2 << v_n_bits);
30522 v_n_bits += 8;
30523 }
30524 v_length = (((v_length + 253 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 255) + 3);
30525 v_bits >>= v_table_entry_n_bits;
30526 v_n_bits -= v_table_entry_n_bits;
30527 }
30528 while (true) {
30529 v_table_entry = self->private_data.f_huffs[1][(v_bits & v_dmask)];
30530 v_table_entry_n_bits = (v_table_entry & 15);
30531 if (v_n_bits >= v_table_entry_n_bits) {
30532 v_bits >>= v_table_entry_n_bits;
30533 v_n_bits -= v_table_entry_n_bits;
30534 goto label__2__break;
30535 }
30536 {
30537 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
30538 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30539 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30540 goto suspend;
30541 }
30542 uint32_t t_3 = *iop_a_src++;
30543 v_b3 = t_3;
30544 }
30545 v_bits |= (v_b3 << v_n_bits);
30546 v_n_bits += 8;
30547 }
30548 label__2__break:;
30549 if ((v_table_entry >> 28) == 1) {
30550 v_redir_top = ((v_table_entry >> 8) & 65535);
30551 v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1);
30552 while (true) {
30553 v_table_entry = self->private_data.f_huffs[1][((v_redir_top + (v_bits & v_redir_mask)) & 1023)];
30554 v_table_entry_n_bits = (v_table_entry & 15);
30555 if (v_n_bits >= v_table_entry_n_bits) {
30556 v_bits >>= v_table_entry_n_bits;
30557 v_n_bits -= v_table_entry_n_bits;
30558 goto label__3__break;
30559 }
30560 {
30561 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
30562 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30563 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30564 goto suspend;
30565 }
30566 uint32_t t_4 = *iop_a_src++;
30567 v_b4 = t_4;
30568 }
30569 v_bits |= (v_b4 << v_n_bits);
30570 v_n_bits += 8;
30571 }
30572 label__3__break:;
30573 }
30574 if ((v_table_entry >> 24) != 64) {
30575 if ((v_table_entry >> 24) == 8) {
30576 status = wuffs_base__make_status(wuffs_deflate__error__bad_huffman_code);
30577 goto exit;
30578 }
30579 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_huffman_decoder_state);
30580 goto exit;
30581 }
30582 v_dist_minus_1 = ((v_table_entry >> 8) & 32767);
30583 v_table_entry_n_bits = ((v_table_entry >> 4) & 15);
30584 if (v_table_entry_n_bits > 0) {
30585 while (v_n_bits < v_table_entry_n_bits) {
30586 {
30587 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
30588 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
30589 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30590 goto suspend;
30591 }
30592 uint32_t t_5 = *iop_a_src++;
30593 v_b5 = t_5;
30594 }
30595 v_bits |= (v_b5 << v_n_bits);
30596 v_n_bits += 8;
30597 }
30598 v_dist_minus_1 = ((v_dist_minus_1 + ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_table_entry_n_bits))) & 32767);
30599 v_bits >>= v_table_entry_n_bits;
30600 v_n_bits -= v_table_entry_n_bits;
30601 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110030602 label__inner__continue:;
Nigel Taoe360a532021-04-05 22:47:03 +100030603 while (true) {
30604 if (((uint64_t)((v_dist_minus_1 + 1))) > ((uint64_t)(iop_a_dst - io0_a_dst))) {
30605 v_hdist = ((uint32_t)((((uint64_t)((v_dist_minus_1 + 1))) - ((uint64_t)(iop_a_dst - io0_a_dst)))));
Nigel Taoebbecaa2022-01-08 14:08:27 +110030606 if (v_hdist < v_length) {
Nigel Taoe360a532021-04-05 22:47:03 +100030607 v_hlen = v_hdist;
30608 } else {
30609 v_hlen = v_length;
Nigel Taoe360a532021-04-05 22:47:03 +100030610 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100030611 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 +100030612 if (self->private_impl.f_history_index < v_hdist) {
30613 status = wuffs_base__make_status(wuffs_deflate__error__bad_distance);
30614 goto exit;
30615 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110030616 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_slice(
Nigel Tao123a5c62022-06-03 14:17:20 +100030617 &iop_a_dst, io2_a_dst,v_hlen, wuffs_base__make_slice_u8_ij(self->private_data.f_history, ((self->private_impl.f_history_index - v_hdist) & 32767), 33025));
Nigel Taoebbecaa2022-01-08 14:08:27 +110030618 if (v_n_copied < v_hlen) {
30619 v_length -= v_n_copied;
Nigel Taoe360a532021-04-05 22:47:03 +100030620 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
30621 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
Nigel Taoebbecaa2022-01-08 14:08:27 +110030622 goto label__inner__continue;
Nigel Taoe360a532021-04-05 22:47:03 +100030623 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110030624 v_length -= v_hlen;
Nigel Taoe360a532021-04-05 22:47:03 +100030625 if (v_length == 0) {
30626 goto label__loop__continue;
30627 }
30628 }
30629 v_n_copied = wuffs_base__io_writer__limited_copy_u32_from_history(
30630 &iop_a_dst, io0_a_dst, io2_a_dst, v_length, (v_dist_minus_1 + 1));
30631 if (v_length <= v_n_copied) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110030632 goto label__loop__continue;
Nigel Taoe360a532021-04-05 22:47:03 +100030633 }
30634 v_length -= v_n_copied;
30635 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
Nigel Taoebbecaa2022-01-08 14:08:27 +110030636 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
Nigel Taoe360a532021-04-05 22:47:03 +100030637 }
Nigel Taoe360a532021-04-05 22:47:03 +100030638 }
30639 label__loop__break:;
30640 self->private_impl.f_bits = v_bits;
30641 self->private_impl.f_n_bits = v_n_bits;
30642 if ((self->private_impl.f_n_bits >= 8) || ((self->private_impl.f_bits >> (self->private_impl.f_n_bits & 7)) != 0)) {
30643 status = wuffs_base__make_status(wuffs_deflate__error__internal_error_inconsistent_n_bits);
30644 goto exit;
30645 }
30646
Nigel Taoe360a532021-04-05 22:47:03 +100030647 ok:
30648 self->private_impl.p_decode_huffman_slow[0] = 0;
30649 goto exit;
30650 }
30651
30652 goto suspend;
30653 suspend:
30654 self->private_impl.p_decode_huffman_slow[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30655 self->private_data.s_decode_huffman_slow[0].v_bits = v_bits;
30656 self->private_data.s_decode_huffman_slow[0].v_n_bits = v_n_bits;
Nigel Taoe360a532021-04-05 22:47:03 +100030657 self->private_data.s_decode_huffman_slow[0].v_table_entry_n_bits = v_table_entry_n_bits;
30658 self->private_data.s_decode_huffman_slow[0].v_lmask = v_lmask;
30659 self->private_data.s_decode_huffman_slow[0].v_dmask = v_dmask;
30660 self->private_data.s_decode_huffman_slow[0].v_redir_top = v_redir_top;
30661 self->private_data.s_decode_huffman_slow[0].v_redir_mask = v_redir_mask;
30662 self->private_data.s_decode_huffman_slow[0].v_length = v_length;
30663 self->private_data.s_decode_huffman_slow[0].v_dist_minus_1 = v_dist_minus_1;
Nigel Taoe360a532021-04-05 22:47:03 +100030664
30665 goto exit;
30666 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110030667 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030668 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
30669 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110030670 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030671 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
30672 }
30673
30674 return status;
30675}
30676
30677#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__DEFLATE)
30678
30679#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW)
30680
30681// ---------------- Status Codes Implementations
30682
30683const char wuffs_lzw__error__bad_code[] = "#lzw: bad code";
30684const char wuffs_lzw__error__internal_error_inconsistent_i_o[] = "#lzw: internal error: inconsistent I/O";
30685
30686// ---------------- Private Consts
30687
30688// ---------------- Private Initializer Prototypes
30689
30690// ---------------- Private Function Prototypes
30691
30692static wuffs_base__empty_struct
30693wuffs_lzw__decoder__read_from(
30694 wuffs_lzw__decoder* self,
30695 wuffs_base__io_buffer* a_src);
30696
30697static wuffs_base__status
30698wuffs_lzw__decoder__write_to(
30699 wuffs_lzw__decoder* self,
30700 wuffs_base__io_buffer* a_dst);
30701
30702// ---------------- VTables
30703
30704const wuffs_base__io_transformer__func_ptrs
30705wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer = {
30706 (wuffs_base__empty_struct(*)(void*,
30707 uint32_t,
30708 bool))(&wuffs_lzw__decoder__set_quirk_enabled),
30709 (wuffs_base__status(*)(void*,
30710 wuffs_base__io_buffer*,
30711 wuffs_base__io_buffer*,
30712 wuffs_base__slice_u8))(&wuffs_lzw__decoder__transform_io),
30713 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_lzw__decoder__workbuf_len),
30714};
30715
30716// ---------------- Initializer Implementations
30717
30718wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
30719wuffs_lzw__decoder__initialize(
30720 wuffs_lzw__decoder* self,
30721 size_t sizeof_star_self,
30722 uint64_t wuffs_version,
30723 uint32_t options){
30724 if (!self) {
30725 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
30726 }
30727 if (sizeof(*self) != sizeof_star_self) {
30728 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
30729 }
30730 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
30731 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
30732 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
30733 }
30734
30735 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
30736 // The whole point of this if-check is to detect an uninitialized *self.
30737 // We disable the warning on GCC. Clang-5.0 does not have this warning.
30738#if !defined(__clang__) && defined(__GNUC__)
30739#pragma GCC diagnostic push
30740#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
30741#endif
30742 if (self->private_impl.magic != 0) {
30743 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
30744 }
30745#if !defined(__clang__) && defined(__GNUC__)
30746#pragma GCC diagnostic pop
30747#endif
30748 } else {
30749 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
30750 memset(self, 0, sizeof(*self));
30751 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
30752 } else {
30753 memset(&(self->private_impl), 0, sizeof(self->private_impl));
30754 }
30755 }
30756
30757 self->private_impl.magic = WUFFS_BASE__MAGIC;
30758 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
30759 wuffs_base__io_transformer__vtable_name;
30760 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
30761 (const void*)(&wuffs_lzw__decoder__func_ptrs_for__wuffs_base__io_transformer);
30762 return wuffs_base__make_status(NULL);
30763}
30764
30765wuffs_lzw__decoder*
30766wuffs_lzw__decoder__alloc() {
30767 wuffs_lzw__decoder* x =
30768 (wuffs_lzw__decoder*)(calloc(sizeof(wuffs_lzw__decoder), 1));
30769 if (!x) {
30770 return NULL;
30771 }
30772 if (wuffs_lzw__decoder__initialize(
30773 x, sizeof(wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
30774 free(x);
30775 return NULL;
30776 }
30777 return x;
30778}
30779
30780size_t
30781sizeof__wuffs_lzw__decoder() {
30782 return sizeof(wuffs_lzw__decoder);
30783}
30784
30785// ---------------- Function Implementations
30786
30787// -------- func lzw.decoder.set_quirk_enabled
30788
30789WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
30790wuffs_lzw__decoder__set_quirk_enabled(
30791 wuffs_lzw__decoder* self,
30792 uint32_t a_quirk,
30793 bool a_enabled) {
30794 return wuffs_base__make_empty_struct();
30795}
30796
30797// -------- func lzw.decoder.set_literal_width
30798
30799WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
30800wuffs_lzw__decoder__set_literal_width(
30801 wuffs_lzw__decoder* self,
30802 uint32_t a_lw) {
30803 if (!self) {
30804 return wuffs_base__make_empty_struct();
30805 }
30806 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
30807 return wuffs_base__make_empty_struct();
30808 }
30809 if (a_lw > 8) {
30810 self->private_impl.magic = WUFFS_BASE__DISABLED;
30811 return wuffs_base__make_empty_struct();
30812 }
30813
30814 self->private_impl.f_set_literal_width_arg = (a_lw + 1);
30815 return wuffs_base__make_empty_struct();
30816}
30817
30818// -------- func lzw.decoder.workbuf_len
30819
30820WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
30821wuffs_lzw__decoder__workbuf_len(
30822 const wuffs_lzw__decoder* self) {
30823 if (!self) {
30824 return wuffs_base__utility__empty_range_ii_u64();
30825 }
30826 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
30827 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
30828 return wuffs_base__utility__empty_range_ii_u64();
30829 }
30830
30831 return wuffs_base__utility__make_range_ii_u64(0, 0);
30832}
30833
30834// -------- func lzw.decoder.transform_io
30835
30836WUFFS_BASE__MAYBE_STATIC wuffs_base__status
30837wuffs_lzw__decoder__transform_io(
30838 wuffs_lzw__decoder* self,
30839 wuffs_base__io_buffer* a_dst,
30840 wuffs_base__io_buffer* a_src,
30841 wuffs_base__slice_u8 a_workbuf) {
30842 if (!self) {
30843 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
30844 }
30845 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
30846 return wuffs_base__make_status(
30847 (self->private_impl.magic == WUFFS_BASE__DISABLED)
30848 ? wuffs_base__error__disabled_by_previous_error
30849 : wuffs_base__error__initialize_not_called);
30850 }
30851 if (!a_dst || !a_src) {
30852 self->private_impl.magic = WUFFS_BASE__DISABLED;
30853 return wuffs_base__make_status(wuffs_base__error__bad_argument);
30854 }
30855 if ((self->private_impl.active_coroutine != 0) &&
30856 (self->private_impl.active_coroutine != 1)) {
30857 self->private_impl.magic = WUFFS_BASE__DISABLED;
30858 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
30859 }
30860 self->private_impl.active_coroutine = 0;
30861 wuffs_base__status status = wuffs_base__make_status(NULL);
30862
30863 uint32_t v_i = 0;
30864
30865 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
30866 switch (coro_susp_point) {
30867 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
30868
30869 self->private_impl.f_literal_width = 8;
30870 if (self->private_impl.f_set_literal_width_arg > 0) {
30871 self->private_impl.f_literal_width = (self->private_impl.f_set_literal_width_arg - 1);
30872 }
30873 self->private_impl.f_clear_code = (((uint32_t)(1)) << self->private_impl.f_literal_width);
30874 self->private_impl.f_end_code = (self->private_impl.f_clear_code + 1);
30875 self->private_impl.f_save_code = self->private_impl.f_end_code;
30876 self->private_impl.f_prev_code = self->private_impl.f_end_code;
30877 self->private_impl.f_width = (self->private_impl.f_literal_width + 1);
30878 self->private_impl.f_bits = 0;
30879 self->private_impl.f_n_bits = 0;
30880 self->private_impl.f_output_ri = 0;
30881 self->private_impl.f_output_wi = 0;
30882 v_i = 0;
30883 while (v_i < self->private_impl.f_clear_code) {
30884 self->private_data.f_lm1s[v_i] = 0;
30885 self->private_data.f_suffixes[v_i][0] = ((uint8_t)(v_i));
30886 v_i += 1;
30887 }
30888 label__0__continue:;
30889 while (true) {
30890 wuffs_lzw__decoder__read_from(self, a_src);
30891 if (self->private_impl.f_output_wi > 0) {
30892 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
30893 status = wuffs_lzw__decoder__write_to(self, a_dst);
30894 if (status.repr) {
30895 goto suspend;
30896 }
30897 }
30898 if (self->private_impl.f_read_from_return_value == 0) {
30899 goto label__0__break;
30900 } else if (self->private_impl.f_read_from_return_value == 1) {
30901 goto label__0__continue;
30902 } else if (self->private_impl.f_read_from_return_value == 2) {
30903 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
30904 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
30905 } else if (self->private_impl.f_read_from_return_value == 3) {
30906 status = wuffs_base__make_status(wuffs_lzw__error__bad_code);
30907 goto exit;
30908 } else {
30909 status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o);
30910 goto exit;
30911 }
30912 }
30913 label__0__break:;
30914
Nigel Taoe360a532021-04-05 22:47:03 +100030915 ok:
30916 self->private_impl.p_transform_io[0] = 0;
30917 goto exit;
30918 }
30919
30920 goto suspend;
30921 suspend:
30922 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
30923 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
30924
30925 goto exit;
30926 exit:
30927 if (wuffs_base__status__is_error(&status)) {
30928 self->private_impl.magic = WUFFS_BASE__DISABLED;
30929 }
30930 return status;
30931}
30932
30933// -------- func lzw.decoder.read_from
30934
30935static wuffs_base__empty_struct
30936wuffs_lzw__decoder__read_from(
30937 wuffs_lzw__decoder* self,
30938 wuffs_base__io_buffer* a_src) {
30939 uint32_t v_clear_code = 0;
30940 uint32_t v_end_code = 0;
30941 uint32_t v_save_code = 0;
30942 uint32_t v_prev_code = 0;
30943 uint32_t v_width = 0;
30944 uint32_t v_bits = 0;
30945 uint32_t v_n_bits = 0;
30946 uint32_t v_output_wi = 0;
30947 uint32_t v_code = 0;
30948 uint32_t v_c = 0;
30949 uint32_t v_o = 0;
30950 uint32_t v_steps = 0;
30951 uint8_t v_first_byte = 0;
30952 uint16_t v_lm1_b = 0;
30953 uint16_t v_lm1_a = 0;
30954
30955 const uint8_t* iop_a_src = NULL;
30956 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30957 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
30958 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110030959 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100030960 io0_a_src = a_src->data.ptr;
30961 io1_a_src = io0_a_src + a_src->meta.ri;
30962 iop_a_src = io1_a_src;
30963 io2_a_src = io0_a_src + a_src->meta.wi;
30964 }
30965
30966 v_clear_code = self->private_impl.f_clear_code;
30967 v_end_code = self->private_impl.f_end_code;
30968 v_save_code = self->private_impl.f_save_code;
30969 v_prev_code = self->private_impl.f_prev_code;
30970 v_width = self->private_impl.f_width;
30971 v_bits = self->private_impl.f_bits;
30972 v_n_bits = self->private_impl.f_n_bits;
30973 v_output_wi = self->private_impl.f_output_wi;
30974 while (true) {
30975 if (v_n_bits < v_width) {
30976 if (((uint64_t)(io2_a_src - iop_a_src)) >= 4) {
30977 v_bits |= ((uint32_t)(wuffs_base__peek_u32le__no_bounds_check(iop_a_src) << v_n_bits));
30978 iop_a_src += ((31 - v_n_bits) >> 3);
30979 v_n_bits |= 24;
30980 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
30981 self->private_impl.f_read_from_return_value = 2;
30982 goto label__0__break;
30983 } else {
30984 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30985 iop_a_src += 1;
30986 v_n_bits += 8;
30987 if (v_n_bits >= v_width) {
30988 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
30989 self->private_impl.f_read_from_return_value = 2;
30990 goto label__0__break;
30991 } else {
30992 v_bits |= (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) << v_n_bits);
30993 iop_a_src += 1;
30994 v_n_bits += 8;
30995 if (v_n_bits < v_width) {
30996 self->private_impl.f_read_from_return_value = 4;
30997 goto label__0__break;
30998 }
30999 }
31000 }
31001 }
31002 v_code = ((v_bits) & WUFFS_BASE__LOW_BITS_MASK__U32(v_width));
31003 v_bits >>= v_width;
31004 v_n_bits -= v_width;
31005 if (v_code < v_clear_code) {
31006 self->private_data.f_output[v_output_wi] = ((uint8_t)(v_code));
31007 v_output_wi = ((v_output_wi + 1) & 8191);
31008 if (v_save_code <= 4095) {
31009 v_lm1_a = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1)) & 4095);
31010 self->private_data.f_lm1s[v_save_code] = v_lm1_a;
31011 if ((v_lm1_a % 8) != 0) {
31012 self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code];
31013 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]));
31014 self->private_data.f_suffixes[v_save_code][(v_lm1_a % 8)] = ((uint8_t)(v_code));
31015 } else {
31016 self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code));
31017 self->private_data.f_suffixes[v_save_code][0] = ((uint8_t)(v_code));
31018 }
31019 v_save_code += 1;
31020 if (v_width < 12) {
31021 v_width += (1 & (v_save_code >> v_width));
31022 }
31023 v_prev_code = v_code;
31024 }
31025 } else if (v_code <= v_end_code) {
31026 if (v_code == v_end_code) {
31027 self->private_impl.f_read_from_return_value = 0;
31028 goto label__0__break;
31029 }
31030 v_save_code = v_end_code;
31031 v_prev_code = v_end_code;
31032 v_width = (self->private_impl.f_literal_width + 1);
31033 } else if (v_code <= v_save_code) {
31034 v_c = v_code;
31035 if (v_code == v_save_code) {
31036 v_c = v_prev_code;
31037 }
31038 v_o = ((v_output_wi + (((uint32_t)(self->private_data.f_lm1s[v_c])) & 4294967288)) & 8191);
31039 v_output_wi = ((v_output_wi + 1 + ((uint32_t)(self->private_data.f_lm1s[v_c]))) & 8191);
31040 v_steps = (((uint32_t)(self->private_data.f_lm1s[v_c])) >> 3);
31041 while (true) {
31042 memcpy((self->private_data.f_output)+(v_o), (self->private_data.f_suffixes[v_c]), 8);
31043 if (v_steps <= 0) {
31044 goto label__1__break;
31045 }
31046 v_steps -= 1;
31047 v_o = (((uint32_t)(v_o - 8)) & 8191);
31048 v_c = ((uint32_t)(self->private_impl.f_prefixes[v_c]));
31049 }
31050 label__1__break:;
31051 v_first_byte = self->private_data.f_suffixes[v_c][0];
31052 if (v_code == v_save_code) {
31053 self->private_data.f_output[v_output_wi] = v_first_byte;
31054 v_output_wi = ((v_output_wi + 1) & 8191);
31055 }
31056 if (v_save_code <= 4095) {
31057 v_lm1_b = (((uint16_t)(self->private_data.f_lm1s[v_prev_code] + 1)) & 4095);
31058 self->private_data.f_lm1s[v_save_code] = v_lm1_b;
31059 if ((v_lm1_b % 8) != 0) {
31060 self->private_impl.f_prefixes[v_save_code] = self->private_impl.f_prefixes[v_prev_code];
31061 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]));
31062 self->private_data.f_suffixes[v_save_code][(v_lm1_b % 8)] = v_first_byte;
31063 } else {
31064 self->private_impl.f_prefixes[v_save_code] = ((uint16_t)(v_prev_code));
31065 self->private_data.f_suffixes[v_save_code][0] = ((uint8_t)(v_first_byte));
31066 }
31067 v_save_code += 1;
31068 if (v_width < 12) {
31069 v_width += (1 & (v_save_code >> v_width));
31070 }
31071 v_prev_code = v_code;
31072 }
31073 } else {
31074 self->private_impl.f_read_from_return_value = 3;
31075 goto label__0__break;
31076 }
31077 if (v_output_wi > 4095) {
31078 self->private_impl.f_read_from_return_value = 1;
31079 goto label__0__break;
31080 }
31081 }
31082 label__0__break:;
31083 if (self->private_impl.f_read_from_return_value != 2) {
31084 while (v_n_bits >= 8) {
31085 v_n_bits -= 8;
31086 if (iop_a_src > io1_a_src) {
31087 iop_a_src--;
31088 } else {
31089 self->private_impl.f_read_from_return_value = 4;
31090 goto label__2__break;
31091 }
31092 }
31093 label__2__break:;
31094 }
31095 self->private_impl.f_save_code = v_save_code;
31096 self->private_impl.f_prev_code = v_prev_code;
31097 self->private_impl.f_width = v_width;
31098 self->private_impl.f_bits = v_bits;
31099 self->private_impl.f_n_bits = v_n_bits;
31100 self->private_impl.f_output_wi = v_output_wi;
Nigel Taoa0041ac2022-10-20 11:24:24 +110031101 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031102 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31103 }
31104
31105 return wuffs_base__make_empty_struct();
31106}
31107
31108// -------- func lzw.decoder.write_to
31109
31110static wuffs_base__status
31111wuffs_lzw__decoder__write_to(
31112 wuffs_lzw__decoder* self,
31113 wuffs_base__io_buffer* a_dst) {
31114 wuffs_base__status status = wuffs_base__make_status(NULL);
31115
31116 wuffs_base__slice_u8 v_s = {0};
31117 uint64_t v_n = 0;
31118
31119 uint8_t* iop_a_dst = NULL;
31120 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31121 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31122 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110031123 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031124 io0_a_dst = a_dst->data.ptr;
31125 io1_a_dst = io0_a_dst + a_dst->meta.wi;
31126 iop_a_dst = io1_a_dst;
31127 io2_a_dst = io0_a_dst + a_dst->data.len;
31128 if (a_dst->meta.closed) {
31129 io2_a_dst = iop_a_dst;
31130 }
31131 }
31132
31133 uint32_t coro_susp_point = self->private_impl.p_write_to[0];
31134 switch (coro_susp_point) {
31135 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31136
31137 while (self->private_impl.f_output_wi > 0) {
31138 if (self->private_impl.f_output_ri > self->private_impl.f_output_wi) {
31139 status = wuffs_base__make_status(wuffs_lzw__error__internal_error_inconsistent_i_o);
31140 goto exit;
31141 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031142 v_s = wuffs_base__make_slice_u8_ij(self->private_data.f_output,
Nigel Taoe360a532021-04-05 22:47:03 +100031143 self->private_impl.f_output_ri,
31144 self->private_impl.f_output_wi);
31145 v_n = wuffs_base__io_writer__copy_from_slice(&iop_a_dst, io2_a_dst,v_s);
31146 if (v_n == ((uint64_t)(v_s.len))) {
31147 self->private_impl.f_output_ri = 0;
31148 self->private_impl.f_output_wi = 0;
31149 status = wuffs_base__make_status(NULL);
31150 goto ok;
31151 }
31152 self->private_impl.f_output_ri = (((uint32_t)(self->private_impl.f_output_ri + ((uint32_t)((v_n & 4294967295))))) & 8191);
31153 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
31154 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
31155 }
31156
Nigel Taoe360a532021-04-05 22:47:03 +100031157 ok:
31158 self->private_impl.p_write_to[0] = 0;
31159 goto exit;
31160 }
31161
31162 goto suspend;
31163 suspend:
31164 self->private_impl.p_write_to[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
31165
31166 goto exit;
31167 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110031168 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031169 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
31170 }
31171
31172 return status;
31173}
31174
31175// -------- func lzw.decoder.flush
31176
31177WUFFS_BASE__MAYBE_STATIC wuffs_base__slice_u8
31178wuffs_lzw__decoder__flush(
31179 wuffs_lzw__decoder* self) {
31180 if (!self) {
31181 return wuffs_base__make_slice_u8(NULL, 0);
31182 }
31183 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31184 return wuffs_base__make_slice_u8(NULL, 0);
31185 }
31186
31187 wuffs_base__slice_u8 v_s = {0};
31188
31189 if (self->private_impl.f_output_ri <= self->private_impl.f_output_wi) {
Nigel Tao123a5c62022-06-03 14:17:20 +100031190 v_s = wuffs_base__make_slice_u8_ij(self->private_data.f_output,
Nigel Taoe360a532021-04-05 22:47:03 +100031191 self->private_impl.f_output_ri,
31192 self->private_impl.f_output_wi);
31193 }
31194 self->private_impl.f_output_ri = 0;
31195 self->private_impl.f_output_wi = 0;
31196 return v_s;
31197}
31198
31199#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__LZW)
31200
31201#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
31202
31203// ---------------- Status Codes Implementations
31204
31205const char wuffs_gif__error__bad_extension_label[] = "#gif: bad extension label";
31206const char wuffs_gif__error__bad_frame_size[] = "#gif: bad frame size";
31207const char wuffs_gif__error__bad_graphic_control[] = "#gif: bad graphic control";
31208const char wuffs_gif__error__bad_header[] = "#gif: bad header";
31209const char wuffs_gif__error__bad_literal_width[] = "#gif: bad literal width";
31210const char wuffs_gif__error__bad_palette[] = "#gif: bad palette";
31211const char wuffs_gif__error__internal_error_inconsistent_ri_wi[] = "#gif: internal error: inconsistent ri/wi";
31212
31213// ---------------- Private Consts
31214
31215static const uint32_t
31216WUFFS_GIF__INTERLACE_START[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
31217 4294967295, 1, 2, 4, 0,
31218};
31219
31220static const uint8_t
31221WUFFS_GIF__INTERLACE_DELTA[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
31222 1, 2, 4, 8, 8,
31223};
31224
31225static const uint8_t
31226WUFFS_GIF__INTERLACE_COUNT[5] WUFFS_BASE__POTENTIALLY_UNUSED = {
31227 0, 1, 2, 4, 8,
31228};
31229
31230static const uint8_t
31231WUFFS_GIF__ANIMEXTS1DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
31232 65, 78, 73, 77, 69, 88, 84, 83,
31233 49, 46, 48,
31234};
31235
31236static const uint8_t
31237WUFFS_GIF__NETSCAPE2DOT0[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
31238 78, 69, 84, 83, 67, 65, 80, 69,
31239 50, 46, 48,
31240};
31241
31242static const uint8_t
31243WUFFS_GIF__ICCRGBG1012[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
31244 73, 67, 67, 82, 71, 66, 71, 49,
31245 48, 49, 50,
31246};
31247
31248static const uint8_t
31249WUFFS_GIF__XMPDATAXMP[11] WUFFS_BASE__POTENTIALLY_UNUSED = {
31250 88, 77, 80, 32, 68, 97, 116, 97,
31251 88, 77, 80,
31252};
31253
31254#define WUFFS_GIF__QUIRKS_BASE 1041635328
31255
31256#define WUFFS_GIF__QUIRKS_COUNT 7
31257
31258// ---------------- Private Initializer Prototypes
31259
31260// ---------------- Private Function Prototypes
31261
31262static wuffs_base__status
31263wuffs_gif__decoder__skip_frame(
31264 wuffs_gif__decoder* self,
31265 wuffs_base__io_buffer* a_src);
31266
31267static wuffs_base__empty_struct
31268wuffs_gif__decoder__reset_gc(
31269 wuffs_gif__decoder* self);
31270
31271static wuffs_base__status
31272wuffs_gif__decoder__decode_up_to_id_part1(
31273 wuffs_gif__decoder* self,
31274 wuffs_base__io_buffer* a_src);
31275
31276static wuffs_base__status
31277wuffs_gif__decoder__decode_header(
31278 wuffs_gif__decoder* self,
31279 wuffs_base__io_buffer* a_src);
31280
31281static wuffs_base__status
31282wuffs_gif__decoder__decode_lsd(
31283 wuffs_gif__decoder* self,
31284 wuffs_base__io_buffer* a_src);
31285
31286static wuffs_base__status
31287wuffs_gif__decoder__decode_extension(
31288 wuffs_gif__decoder* self,
31289 wuffs_base__io_buffer* a_src);
31290
31291static wuffs_base__status
31292wuffs_gif__decoder__skip_blocks(
31293 wuffs_gif__decoder* self,
31294 wuffs_base__io_buffer* a_src);
31295
31296static wuffs_base__status
31297wuffs_gif__decoder__decode_ae(
31298 wuffs_gif__decoder* self,
31299 wuffs_base__io_buffer* a_src);
31300
31301static wuffs_base__status
31302wuffs_gif__decoder__decode_gc(
31303 wuffs_gif__decoder* self,
31304 wuffs_base__io_buffer* a_src);
31305
31306static wuffs_base__status
31307wuffs_gif__decoder__decode_id_part0(
31308 wuffs_gif__decoder* self,
31309 wuffs_base__io_buffer* a_src);
31310
31311static wuffs_base__status
31312wuffs_gif__decoder__decode_id_part1(
31313 wuffs_gif__decoder* self,
31314 wuffs_base__pixel_buffer* a_dst,
31315 wuffs_base__io_buffer* a_src,
31316 wuffs_base__pixel_blend a_blend);
31317
31318static wuffs_base__status
31319wuffs_gif__decoder__decode_id_part2(
31320 wuffs_gif__decoder* self,
31321 wuffs_base__pixel_buffer* a_dst,
31322 wuffs_base__io_buffer* a_src,
31323 wuffs_base__slice_u8 a_workbuf);
31324
31325static wuffs_base__status
31326wuffs_gif__decoder__copy_to_image_buffer(
31327 wuffs_gif__decoder* self,
31328 wuffs_base__pixel_buffer* a_pb,
31329 wuffs_base__slice_u8 a_src);
31330
31331// ---------------- VTables
31332
31333const wuffs_base__image_decoder__func_ptrs
31334wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder = {
31335 (wuffs_base__status(*)(void*,
31336 wuffs_base__pixel_buffer*,
31337 wuffs_base__io_buffer*,
31338 wuffs_base__pixel_blend,
31339 wuffs_base__slice_u8,
31340 wuffs_base__decode_frame_options*))(&wuffs_gif__decoder__decode_frame),
31341 (wuffs_base__status(*)(void*,
31342 wuffs_base__frame_config*,
31343 wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_frame_config),
31344 (wuffs_base__status(*)(void*,
31345 wuffs_base__image_config*,
31346 wuffs_base__io_buffer*))(&wuffs_gif__decoder__decode_image_config),
31347 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_gif__decoder__frame_dirty_rect),
31348 (uint32_t(*)(const void*))(&wuffs_gif__decoder__num_animation_loops),
31349 (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frame_configs),
31350 (uint64_t(*)(const void*))(&wuffs_gif__decoder__num_decoded_frames),
31351 (wuffs_base__status(*)(void*,
31352 uint64_t,
31353 uint64_t))(&wuffs_gif__decoder__restart_frame),
31354 (wuffs_base__empty_struct(*)(void*,
31355 uint32_t,
31356 bool))(&wuffs_gif__decoder__set_quirk_enabled),
31357 (wuffs_base__empty_struct(*)(void*,
31358 uint32_t,
31359 bool))(&wuffs_gif__decoder__set_report_metadata),
31360 (wuffs_base__status(*)(void*,
31361 wuffs_base__io_buffer*,
31362 wuffs_base__more_information*,
31363 wuffs_base__io_buffer*))(&wuffs_gif__decoder__tell_me_more),
31364 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gif__decoder__workbuf_len),
31365};
31366
31367// ---------------- Initializer Implementations
31368
31369wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
31370wuffs_gif__decoder__initialize(
31371 wuffs_gif__decoder* self,
31372 size_t sizeof_star_self,
31373 uint64_t wuffs_version,
31374 uint32_t options){
31375 if (!self) {
31376 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31377 }
31378 if (sizeof(*self) != sizeof_star_self) {
31379 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
31380 }
31381 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
31382 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
31383 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
31384 }
31385
31386 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
31387 // The whole point of this if-check is to detect an uninitialized *self.
31388 // We disable the warning on GCC. Clang-5.0 does not have this warning.
31389#if !defined(__clang__) && defined(__GNUC__)
31390#pragma GCC diagnostic push
31391#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
31392#endif
31393 if (self->private_impl.magic != 0) {
31394 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
31395 }
31396#if !defined(__clang__) && defined(__GNUC__)
31397#pragma GCC diagnostic pop
31398#endif
31399 } else {
31400 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
31401 memset(self, 0, sizeof(*self));
31402 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
31403 } else {
31404 memset(&(self->private_impl), 0, sizeof(self->private_impl));
31405 }
31406 }
31407
31408 {
31409 wuffs_base__status z = wuffs_lzw__decoder__initialize(
31410 &self->private_data.f_lzw, sizeof(self->private_data.f_lzw), WUFFS_VERSION, options);
31411 if (z.repr) {
31412 return z;
31413 }
31414 }
31415 self->private_impl.magic = WUFFS_BASE__MAGIC;
31416 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
31417 wuffs_base__image_decoder__vtable_name;
31418 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
31419 (const void*)(&wuffs_gif__decoder__func_ptrs_for__wuffs_base__image_decoder);
31420 return wuffs_base__make_status(NULL);
31421}
31422
31423wuffs_gif__decoder*
31424wuffs_gif__decoder__alloc() {
31425 wuffs_gif__decoder* x =
31426 (wuffs_gif__decoder*)(calloc(sizeof(wuffs_gif__decoder), 1));
31427 if (!x) {
31428 return NULL;
31429 }
31430 if (wuffs_gif__decoder__initialize(
31431 x, sizeof(wuffs_gif__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
31432 free(x);
31433 return NULL;
31434 }
31435 return x;
31436}
31437
31438size_t
31439sizeof__wuffs_gif__decoder() {
31440 return sizeof(wuffs_gif__decoder);
31441}
31442
31443// ---------------- Function Implementations
31444
31445// -------- func gif.decoder.set_quirk_enabled
31446
31447WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
31448wuffs_gif__decoder__set_quirk_enabled(
31449 wuffs_gif__decoder* self,
31450 uint32_t a_quirk,
31451 bool a_enabled) {
31452 if (!self) {
31453 return wuffs_base__make_empty_struct();
31454 }
31455 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31456 return wuffs_base__make_empty_struct();
31457 }
31458
31459 if ((self->private_impl.f_call_sequence == 0) && (a_quirk >= 1041635328)) {
31460 a_quirk -= 1041635328;
31461 if (a_quirk < 7) {
31462 self->private_impl.f_quirks[a_quirk] = a_enabled;
31463 }
31464 }
31465 return wuffs_base__make_empty_struct();
31466}
31467
31468// -------- func gif.decoder.decode_image_config
31469
31470WUFFS_BASE__MAYBE_STATIC wuffs_base__status
31471wuffs_gif__decoder__decode_image_config(
31472 wuffs_gif__decoder* self,
31473 wuffs_base__image_config* a_dst,
31474 wuffs_base__io_buffer* a_src) {
31475 if (!self) {
31476 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31477 }
31478 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31479 return wuffs_base__make_status(
31480 (self->private_impl.magic == WUFFS_BASE__DISABLED)
31481 ? wuffs_base__error__disabled_by_previous_error
31482 : wuffs_base__error__initialize_not_called);
31483 }
31484 if (!a_src) {
31485 self->private_impl.magic = WUFFS_BASE__DISABLED;
31486 return wuffs_base__make_status(wuffs_base__error__bad_argument);
31487 }
31488 if ((self->private_impl.active_coroutine != 0) &&
31489 (self->private_impl.active_coroutine != 1)) {
31490 self->private_impl.magic = WUFFS_BASE__DISABLED;
31491 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
31492 }
31493 self->private_impl.active_coroutine = 0;
31494 wuffs_base__status status = wuffs_base__make_status(NULL);
31495
31496 bool v_ffio = false;
31497
31498 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
31499 switch (coro_susp_point) {
31500 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31501
Nigel Tao123a5c62022-06-03 14:17:20 +100031502 if (self->private_impl.f_call_sequence != 0) {
31503 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
31504 goto exit;
31505 } else if ( ! self->private_impl.f_seen_header) {
Nigel Taoe360a532021-04-05 22:47:03 +100031506 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
31507 status = wuffs_gif__decoder__decode_header(self, a_src);
31508 if (status.repr) {
31509 goto suspend;
31510 }
31511 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
31512 status = wuffs_gif__decoder__decode_lsd(self, a_src);
31513 if (status.repr) {
31514 goto suspend;
31515 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031516 self->private_impl.f_seen_header = true;
Nigel Taoe360a532021-04-05 22:47:03 +100031517 }
31518 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
31519 status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
31520 if (status.repr) {
31521 goto suspend;
31522 }
31523 v_ffio = ! self->private_impl.f_gc_has_transparent_index;
31524 if ( ! self->private_impl.f_quirks[2]) {
31525 v_ffio = (v_ffio &&
31526 (self->private_impl.f_frame_rect_x0 == 0) &&
31527 (self->private_impl.f_frame_rect_y0 == 0) &&
31528 (self->private_impl.f_frame_rect_x1 == self->private_impl.f_width) &&
31529 (self->private_impl.f_frame_rect_y1 == self->private_impl.f_height));
31530 } else if (v_ffio) {
31531 self->private_impl.f_black_color_u32_argb_premul = 4278190080;
31532 }
31533 if (self->private_impl.f_background_color_u32_argb_premul == 77) {
31534 self->private_impl.f_background_color_u32_argb_premul = self->private_impl.f_black_color_u32_argb_premul;
31535 }
31536 if (a_dst != NULL) {
31537 wuffs_base__image_config__set(
31538 a_dst,
31539 2198077448,
31540 0,
31541 self->private_impl.f_width,
31542 self->private_impl.f_height,
31543 self->private_impl.f_frame_config_io_position,
31544 v_ffio);
31545 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031546 if (self->private_impl.f_call_sequence == 0) {
31547 self->private_impl.f_call_sequence = 32;
31548 }
Nigel Taoe360a532021-04-05 22:47:03 +100031549
31550 goto ok;
31551 ok:
31552 self->private_impl.p_decode_image_config[0] = 0;
31553 goto exit;
31554 }
31555
31556 goto suspend;
31557 suspend:
31558 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
31559 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
31560
31561 goto exit;
31562 exit:
31563 if (wuffs_base__status__is_error(&status)) {
31564 self->private_impl.magic = WUFFS_BASE__DISABLED;
31565 }
31566 return status;
31567}
31568
31569// -------- func gif.decoder.set_report_metadata
31570
31571WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
31572wuffs_gif__decoder__set_report_metadata(
31573 wuffs_gif__decoder* self,
31574 uint32_t a_fourcc,
31575 bool a_report) {
31576 if (!self) {
31577 return wuffs_base__make_empty_struct();
31578 }
31579 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31580 return wuffs_base__make_empty_struct();
31581 }
31582
31583 if (a_fourcc == 1229144912) {
31584 self->private_impl.f_report_metadata_iccp = a_report;
31585 } else if (a_fourcc == 1481461792) {
31586 self->private_impl.f_report_metadata_xmp = a_report;
31587 }
31588 return wuffs_base__make_empty_struct();
31589}
31590
31591// -------- func gif.decoder.tell_me_more
31592
31593WUFFS_BASE__MAYBE_STATIC wuffs_base__status
31594wuffs_gif__decoder__tell_me_more(
31595 wuffs_gif__decoder* self,
31596 wuffs_base__io_buffer* a_dst,
31597 wuffs_base__more_information* a_minfo,
31598 wuffs_base__io_buffer* a_src) {
31599 if (!self) {
31600 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31601 }
31602 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31603 return wuffs_base__make_status(
31604 (self->private_impl.magic == WUFFS_BASE__DISABLED)
31605 ? wuffs_base__error__disabled_by_previous_error
31606 : wuffs_base__error__initialize_not_called);
31607 }
31608 if (!a_dst || !a_src) {
31609 self->private_impl.magic = WUFFS_BASE__DISABLED;
31610 return wuffs_base__make_status(wuffs_base__error__bad_argument);
31611 }
31612 if ((self->private_impl.active_coroutine != 0) &&
31613 (self->private_impl.active_coroutine != 2)) {
31614 self->private_impl.magic = WUFFS_BASE__DISABLED;
31615 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
31616 }
31617 self->private_impl.active_coroutine = 0;
31618 wuffs_base__status status = wuffs_base__make_status(NULL);
31619
31620 uint64_t v_chunk_length = 0;
31621
31622 const uint8_t* iop_a_src = NULL;
31623 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31624 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31625 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110031626 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031627 io0_a_src = a_src->data.ptr;
31628 io1_a_src = io0_a_src + a_src->meta.ri;
31629 iop_a_src = io1_a_src;
31630 io2_a_src = io0_a_src + a_src->meta.wi;
31631 }
31632
31633 uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0];
31634 switch (coro_susp_point) {
31635 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31636
Nigel Tao123a5c62022-06-03 14:17:20 +100031637 if ((self->private_impl.f_call_sequence & 16) == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100031638 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
31639 goto exit;
31640 }
31641 if (self->private_impl.f_metadata_fourcc == 0) {
31642 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
31643 goto exit;
31644 }
31645 while (true) {
31646 label__0__continue:;
31647 while (true) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100031648 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 +100031649 if (a_minfo != NULL) {
31650 wuffs_base__more_information__set(a_minfo,
31651 2,
31652 0,
31653 self->private_impl.f_metadata_io_position,
31654 0,
31655 0);
31656 }
31657 status = wuffs_base__make_status(wuffs_base__suspension__mispositioned_read);
31658 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
31659 goto label__0__continue;
31660 }
31661 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
31662 if (a_minfo != NULL) {
31663 wuffs_base__more_information__set(a_minfo,
31664 0,
31665 0,
31666 0,
31667 0,
31668 0);
31669 }
31670 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31671 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
31672 goto label__0__continue;
31673 }
31674 goto label__0__break;
31675 }
31676 label__0__break:;
31677 v_chunk_length = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
31678 if (v_chunk_length <= 0) {
31679 iop_a_src += 1;
31680 goto label__1__break;
31681 }
31682 if (self->private_impl.f_metadata_fourcc == 1481461792) {
31683 v_chunk_length += 1;
31684 } else {
31685 iop_a_src += 1;
31686 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100031687 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 +100031688 if (a_minfo != NULL) {
31689 wuffs_base__more_information__set(a_minfo,
31690 3,
31691 self->private_impl.f_metadata_fourcc,
31692 0,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100031693 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 +100031694 self->private_impl.f_metadata_io_position);
31695 }
31696 status = wuffs_base__make_status(wuffs_base__suspension__even_more_information);
31697 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
31698 }
31699 label__1__break:;
31700 if (a_minfo != NULL) {
31701 wuffs_base__more_information__set(a_minfo,
31702 3,
31703 self->private_impl.f_metadata_fourcc,
31704 0,
31705 self->private_impl.f_metadata_io_position,
31706 self->private_impl.f_metadata_io_position);
31707 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031708 self->private_impl.f_call_sequence &= 239;
Nigel Taoe360a532021-04-05 22:47:03 +100031709 self->private_impl.f_metadata_fourcc = 0;
31710 self->private_impl.f_metadata_io_position = 0;
31711 status = wuffs_base__make_status(NULL);
31712 goto ok;
31713
Nigel Taoe360a532021-04-05 22:47:03 +100031714 ok:
31715 self->private_impl.p_tell_me_more[0] = 0;
31716 goto exit;
31717 }
31718
31719 goto suspend;
31720 suspend:
31721 self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
31722 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
31723
31724 goto exit;
31725 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110031726 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031727 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31728 }
31729
31730 if (wuffs_base__status__is_error(&status)) {
31731 self->private_impl.magic = WUFFS_BASE__DISABLED;
31732 }
31733 return status;
31734}
31735
31736// -------- func gif.decoder.num_animation_loops
31737
31738WUFFS_BASE__MAYBE_STATIC uint32_t
31739wuffs_gif__decoder__num_animation_loops(
31740 const wuffs_gif__decoder* self) {
31741 if (!self) {
31742 return 0;
31743 }
31744 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31745 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31746 return 0;
31747 }
31748
Nigel Taobf9dab32021-11-18 19:19:55 +110031749 if (self->private_impl.f_seen_num_animation_loops_value) {
31750 return self->private_impl.f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +100031751 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110031752 if (self->private_impl.f_num_decoded_frame_configs_value > 1) {
31753 return 1;
31754 }
31755 return 0;
Nigel Taoe360a532021-04-05 22:47:03 +100031756}
31757
31758// -------- func gif.decoder.num_decoded_frame_configs
31759
31760WUFFS_BASE__MAYBE_STATIC uint64_t
31761wuffs_gif__decoder__num_decoded_frame_configs(
31762 const wuffs_gif__decoder* self) {
31763 if (!self) {
31764 return 0;
31765 }
31766 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31767 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31768 return 0;
31769 }
31770
31771 return self->private_impl.f_num_decoded_frame_configs_value;
31772}
31773
31774// -------- func gif.decoder.num_decoded_frames
31775
31776WUFFS_BASE__MAYBE_STATIC uint64_t
31777wuffs_gif__decoder__num_decoded_frames(
31778 const wuffs_gif__decoder* self) {
31779 if (!self) {
31780 return 0;
31781 }
31782 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31783 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31784 return 0;
31785 }
31786
31787 return self->private_impl.f_num_decoded_frames_value;
31788}
31789
31790// -------- func gif.decoder.frame_dirty_rect
31791
31792WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
31793wuffs_gif__decoder__frame_dirty_rect(
31794 const wuffs_gif__decoder* self) {
31795 if (!self) {
31796 return wuffs_base__utility__empty_rect_ie_u32();
31797 }
31798 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31799 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31800 return wuffs_base__utility__empty_rect_ie_u32();
31801 }
31802
31803 return wuffs_base__utility__make_rect_ie_u32(
31804 wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width),
31805 wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height),
31806 wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width),
31807 wuffs_base__u32__min(self->private_impl.f_dirty_max_excl_y, self->private_impl.f_height));
31808}
31809
31810// -------- func gif.decoder.workbuf_len
31811
31812WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
31813wuffs_gif__decoder__workbuf_len(
31814 const wuffs_gif__decoder* self) {
31815 if (!self) {
31816 return wuffs_base__utility__empty_range_ii_u64();
31817 }
31818 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
31819 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
31820 return wuffs_base__utility__empty_range_ii_u64();
31821 }
31822
31823 return wuffs_base__utility__make_range_ii_u64(0, 0);
31824}
31825
31826// -------- func gif.decoder.restart_frame
31827
31828WUFFS_BASE__MAYBE_STATIC wuffs_base__status
31829wuffs_gif__decoder__restart_frame(
31830 wuffs_gif__decoder* self,
31831 uint64_t a_index,
31832 uint64_t a_io_position) {
31833 if (!self) {
31834 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31835 }
31836 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31837 return wuffs_base__make_status(
31838 (self->private_impl.magic == WUFFS_BASE__DISABLED)
31839 ? wuffs_base__error__disabled_by_previous_error
31840 : wuffs_base__error__initialize_not_called);
31841 }
31842
Nigel Tao123a5c62022-06-03 14:17:20 +100031843 if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100031844 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
Nigel Tao123a5c62022-06-03 14:17:20 +100031845 } else if (a_io_position == 0) {
31846 return wuffs_base__make_status(wuffs_base__error__bad_argument);
Nigel Taoe360a532021-04-05 22:47:03 +100031847 }
31848 self->private_impl.f_delayed_num_decoded_frames = false;
Nigel Taoe360a532021-04-05 22:47:03 +100031849 self->private_impl.f_frame_config_io_position = a_io_position;
31850 self->private_impl.f_num_decoded_frame_configs_value = a_index;
31851 self->private_impl.f_num_decoded_frames_value = a_index;
31852 wuffs_gif__decoder__reset_gc(self);
Nigel Tao123a5c62022-06-03 14:17:20 +100031853 self->private_impl.f_call_sequence = 40;
Nigel Taoe360a532021-04-05 22:47:03 +100031854 return wuffs_base__make_status(NULL);
31855}
31856
31857// -------- func gif.decoder.decode_frame_config
31858
31859WUFFS_BASE__MAYBE_STATIC wuffs_base__status
31860wuffs_gif__decoder__decode_frame_config(
31861 wuffs_gif__decoder* self,
31862 wuffs_base__frame_config* a_dst,
31863 wuffs_base__io_buffer* a_src) {
31864 if (!self) {
31865 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
31866 }
31867 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
31868 return wuffs_base__make_status(
31869 (self->private_impl.magic == WUFFS_BASE__DISABLED)
31870 ? wuffs_base__error__disabled_by_previous_error
31871 : wuffs_base__error__initialize_not_called);
31872 }
31873 if (!a_src) {
31874 self->private_impl.magic = WUFFS_BASE__DISABLED;
31875 return wuffs_base__make_status(wuffs_base__error__bad_argument);
31876 }
31877 if ((self->private_impl.active_coroutine != 0) &&
31878 (self->private_impl.active_coroutine != 3)) {
31879 self->private_impl.magic = WUFFS_BASE__DISABLED;
31880 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
31881 }
31882 self->private_impl.active_coroutine = 0;
31883 wuffs_base__status status = wuffs_base__make_status(NULL);
31884
31885 uint32_t v_background_color = 0;
31886 uint8_t v_flags = 0;
31887
31888 const uint8_t* iop_a_src = NULL;
31889 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31890 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
31891 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110031892 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100031893 io0_a_src = a_src->data.ptr;
31894 io1_a_src = io0_a_src + a_src->meta.ri;
31895 iop_a_src = io1_a_src;
31896 io2_a_src = io0_a_src + a_src->meta.wi;
31897 }
31898
31899 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
31900 if (coro_susp_point) {
31901 v_background_color = self->private_data.s_decode_frame_config[0].v_background_color;
31902 }
31903 switch (coro_susp_point) {
31904 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
31905
Nigel Taoe360a532021-04-05 22:47:03 +100031906 self->private_impl.f_dirty_max_excl_y = 0;
Nigel Tao123a5c62022-06-03 14:17:20 +100031907 if ((self->private_impl.f_call_sequence & 16) != 0) {
31908 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
31909 goto exit;
31910 } else if (self->private_impl.f_call_sequence == 32) {
31911 } else if (self->private_impl.f_call_sequence < 32) {
31912 if (a_src) {
31913 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
Nigel Taoe360a532021-04-05 22:47:03 +100031914 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031915 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
31916 status = wuffs_gif__decoder__decode_image_config(self, NULL, a_src);
31917 if (a_src) {
31918 iop_a_src = a_src->data.ptr + a_src->meta.ri;
31919 }
31920 if (status.repr) {
31921 goto suspend;
31922 }
31923 } else if (self->private_impl.f_call_sequence == 40) {
31924 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)))) {
31925 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
31926 goto exit;
31927 }
31928 } else if (self->private_impl.f_call_sequence == 64) {
31929 if (a_src) {
31930 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31931 }
31932 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
31933 status = wuffs_gif__decoder__skip_frame(self, a_src);
31934 if (a_src) {
31935 iop_a_src = a_src->data.ptr + a_src->meta.ri;
31936 }
31937 if (status.repr) {
31938 goto suspend;
31939 }
31940 if (self->private_impl.f_call_sequence >= 96) {
31941 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
31942 goto ok;
31943 }
31944 } else {
Nigel Taoe360a532021-04-05 22:47:03 +100031945 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
31946 goto ok;
31947 }
Nigel Tao123a5c62022-06-03 14:17:20 +100031948 if ((self->private_impl.f_num_decoded_frame_configs_value > 0) || (self->private_impl.f_call_sequence == 40)) {
31949 if (a_src) {
31950 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
31951 }
31952 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
31953 status = wuffs_gif__decoder__decode_up_to_id_part1(self, a_src);
31954 if (a_src) {
31955 iop_a_src = a_src->data.ptr + a_src->meta.ri;
31956 }
31957 if (status.repr) {
31958 goto suspend;
31959 }
31960 if (self->private_impl.f_call_sequence >= 96) {
31961 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
31962 goto ok;
31963 }
31964 }
Nigel Taoe360a532021-04-05 22:47:03 +100031965 v_background_color = self->private_impl.f_black_color_u32_argb_premul;
31966 if ( ! self->private_impl.f_gc_has_transparent_index) {
31967 v_background_color = self->private_impl.f_background_color_u32_argb_premul;
31968 if (self->private_impl.f_quirks[1] && (self->private_impl.f_num_decoded_frame_configs_value == 0)) {
31969 while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
31970 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
31971 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
31972 }
31973 v_flags = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
31974 if ((v_flags & 128) != 0) {
31975 v_background_color = self->private_impl.f_black_color_u32_argb_premul;
31976 }
31977 }
31978 }
31979 if (a_dst != NULL) {
31980 wuffs_base__frame_config__set(
31981 a_dst,
31982 wuffs_base__utility__make_rect_ie_u32(
31983 wuffs_base__u32__min(self->private_impl.f_frame_rect_x0, self->private_impl.f_width),
31984 wuffs_base__u32__min(self->private_impl.f_frame_rect_y0, self->private_impl.f_height),
31985 wuffs_base__u32__min(self->private_impl.f_frame_rect_x1, self->private_impl.f_width),
31986 wuffs_base__u32__min(self->private_impl.f_frame_rect_y1, self->private_impl.f_height)),
31987 ((wuffs_base__flicks)(self->private_impl.f_gc_duration)),
31988 self->private_impl.f_num_decoded_frame_configs_value,
31989 self->private_impl.f_frame_config_io_position,
31990 self->private_impl.f_gc_disposal,
31991 ! self->private_impl.f_gc_has_transparent_index,
31992 false,
31993 v_background_color);
31994 }
31995 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1);
Nigel Tao123a5c62022-06-03 14:17:20 +100031996 self->private_impl.f_call_sequence = 64;
Nigel Taoe360a532021-04-05 22:47:03 +100031997
Nigel Taoe360a532021-04-05 22:47:03 +100031998 ok:
31999 self->private_impl.p_decode_frame_config[0] = 0;
32000 goto exit;
32001 }
32002
32003 goto suspend;
32004 suspend:
32005 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32006 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
32007 self->private_data.s_decode_frame_config[0].v_background_color = v_background_color;
32008
32009 goto exit;
32010 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032011 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032012 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32013 }
32014
32015 if (wuffs_base__status__is_error(&status)) {
32016 self->private_impl.magic = WUFFS_BASE__DISABLED;
32017 }
32018 return status;
32019}
32020
32021// -------- func gif.decoder.skip_frame
32022
32023static wuffs_base__status
32024wuffs_gif__decoder__skip_frame(
32025 wuffs_gif__decoder* self,
32026 wuffs_base__io_buffer* a_src) {
32027 wuffs_base__status status = wuffs_base__make_status(NULL);
32028
32029 uint8_t v_flags = 0;
32030 uint8_t v_lw = 0;
32031
32032 const uint8_t* iop_a_src = NULL;
32033 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32034 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32035 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032036 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032037 io0_a_src = a_src->data.ptr;
32038 io1_a_src = io0_a_src + a_src->meta.ri;
32039 iop_a_src = io1_a_src;
32040 io2_a_src = io0_a_src + a_src->meta.wi;
32041 }
32042
32043 uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
32044 switch (coro_susp_point) {
32045 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32046
32047 {
32048 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32049 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32050 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32051 goto suspend;
32052 }
32053 uint8_t t_0 = *iop_a_src++;
32054 v_flags = t_0;
32055 }
32056 if ((v_flags & 128) != 0) {
32057 self->private_data.s_skip_frame[0].scratch = (((uint32_t)(3)) << (1 + (v_flags & 7)));
32058 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32059 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
32060 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
32061 iop_a_src = io2_a_src;
32062 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32063 goto suspend;
32064 }
32065 iop_a_src += self->private_data.s_skip_frame[0].scratch;
32066 }
32067 {
32068 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32069 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32070 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32071 goto suspend;
32072 }
32073 uint8_t t_1 = *iop_a_src++;
32074 v_lw = t_1;
32075 }
32076 if (v_lw > 8) {
32077 status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width);
32078 goto exit;
32079 }
32080 if (a_src) {
32081 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32082 }
32083 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
32084 status = wuffs_gif__decoder__skip_blocks(self, a_src);
32085 if (a_src) {
32086 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32087 }
32088 if (status.repr) {
32089 goto suspend;
32090 }
32091 if (self->private_impl.f_quirks[0]) {
32092 self->private_impl.f_delayed_num_decoded_frames = true;
32093 } else {
32094 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
32095 }
32096 wuffs_gif__decoder__reset_gc(self);
Nigel Tao123a5c62022-06-03 14:17:20 +100032097 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100032098
32099 goto ok;
32100 ok:
32101 self->private_impl.p_skip_frame[0] = 0;
32102 goto exit;
32103 }
32104
32105 goto suspend;
32106 suspend:
32107 self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32108
32109 goto exit;
32110 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032111 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032112 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32113 }
32114
32115 return status;
32116}
32117
32118// -------- func gif.decoder.decode_frame
32119
32120WUFFS_BASE__MAYBE_STATIC wuffs_base__status
32121wuffs_gif__decoder__decode_frame(
32122 wuffs_gif__decoder* self,
32123 wuffs_base__pixel_buffer* a_dst,
32124 wuffs_base__io_buffer* a_src,
32125 wuffs_base__pixel_blend a_blend,
32126 wuffs_base__slice_u8 a_workbuf,
32127 wuffs_base__decode_frame_options* a_opts) {
32128 if (!self) {
32129 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
32130 }
32131 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
32132 return wuffs_base__make_status(
32133 (self->private_impl.magic == WUFFS_BASE__DISABLED)
32134 ? wuffs_base__error__disabled_by_previous_error
32135 : wuffs_base__error__initialize_not_called);
32136 }
32137 if (!a_dst || !a_src) {
32138 self->private_impl.magic = WUFFS_BASE__DISABLED;
32139 return wuffs_base__make_status(wuffs_base__error__bad_argument);
32140 }
32141 if ((self->private_impl.active_coroutine != 0) &&
32142 (self->private_impl.active_coroutine != 4)) {
32143 self->private_impl.magic = WUFFS_BASE__DISABLED;
32144 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
32145 }
32146 self->private_impl.active_coroutine = 0;
32147 wuffs_base__status status = wuffs_base__make_status(NULL);
32148
32149 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
32150 switch (coro_susp_point) {
32151 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32152
Nigel Tao123a5c62022-06-03 14:17:20 +100032153 if (self->private_impl.f_call_sequence == 64) {
32154 } else if (self->private_impl.f_call_sequence < 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100032155 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32156 status = wuffs_gif__decoder__decode_frame_config(self, NULL, a_src);
32157 if (status.repr) {
32158 goto suspend;
32159 }
Nigel Tao123a5c62022-06-03 14:17:20 +100032160 } else {
32161 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
32162 goto ok;
Nigel Taoe360a532021-04-05 22:47:03 +100032163 }
32164 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))) {
32165 status = wuffs_base__make_status(wuffs_gif__error__bad_frame_size);
32166 goto exit;
32167 }
32168 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32169 status = wuffs_gif__decoder__decode_id_part1(self, a_dst, a_src, a_blend);
32170 if (status.repr) {
32171 goto suspend;
32172 }
32173 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32174 status = wuffs_gif__decoder__decode_id_part2(self, a_dst, a_src, a_workbuf);
32175 if (status.repr) {
32176 goto suspend;
32177 }
32178 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
32179 wuffs_gif__decoder__reset_gc(self);
Nigel Tao123a5c62022-06-03 14:17:20 +100032180 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100032181
Nigel Taoe360a532021-04-05 22:47:03 +100032182 ok:
32183 self->private_impl.p_decode_frame[0] = 0;
32184 goto exit;
32185 }
32186
32187 goto suspend;
32188 suspend:
32189 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32190 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0;
32191
32192 goto exit;
32193 exit:
32194 if (wuffs_base__status__is_error(&status)) {
32195 self->private_impl.magic = WUFFS_BASE__DISABLED;
32196 }
32197 return status;
32198}
32199
32200// -------- func gif.decoder.reset_gc
32201
32202static wuffs_base__empty_struct
32203wuffs_gif__decoder__reset_gc(
32204 wuffs_gif__decoder* self) {
Nigel Taoe360a532021-04-05 22:47:03 +100032205 self->private_impl.f_gc_has_transparent_index = false;
32206 self->private_impl.f_gc_transparent_index = 0;
32207 self->private_impl.f_gc_disposal = 0;
32208 self->private_impl.f_gc_duration = 0;
32209 return wuffs_base__make_empty_struct();
32210}
32211
32212// -------- func gif.decoder.decode_up_to_id_part1
32213
32214static wuffs_base__status
32215wuffs_gif__decoder__decode_up_to_id_part1(
32216 wuffs_gif__decoder* self,
32217 wuffs_base__io_buffer* a_src) {
32218 wuffs_base__status status = wuffs_base__make_status(NULL);
32219
32220 uint8_t v_block_type = 0;
32221
32222 const uint8_t* iop_a_src = NULL;
32223 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32224 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32225 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032226 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032227 io0_a_src = a_src->data.ptr;
32228 io1_a_src = io0_a_src + a_src->meta.ri;
32229 iop_a_src = io1_a_src;
32230 io2_a_src = io0_a_src + a_src->meta.wi;
32231 }
32232
32233 uint32_t coro_susp_point = self->private_impl.p_decode_up_to_id_part1[0];
32234 switch (coro_susp_point) {
32235 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32236
Nigel Tao123a5c62022-06-03 14:17:20 +100032237 if ((self->private_impl.f_frame_config_io_position == 0) || (self->private_impl.f_num_decoded_frame_configs_value > 0)) {
32238 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 +100032239 }
32240 while (true) {
32241 {
32242 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32243 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32244 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32245 goto suspend;
32246 }
32247 uint8_t t_0 = *iop_a_src++;
32248 v_block_type = t_0;
32249 }
32250 if (v_block_type == 33) {
32251 if (a_src) {
32252 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32253 }
32254 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32255 status = wuffs_gif__decoder__decode_extension(self, a_src);
32256 if (a_src) {
32257 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32258 }
32259 if (status.repr) {
32260 goto suspend;
32261 }
32262 } else if (v_block_type == 44) {
32263 if (self->private_impl.f_delayed_num_decoded_frames) {
32264 self->private_impl.f_delayed_num_decoded_frames = false;
32265 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
32266 }
32267 if (a_src) {
32268 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32269 }
32270 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32271 status = wuffs_gif__decoder__decode_id_part0(self, a_src);
32272 if (a_src) {
32273 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32274 }
32275 if (status.repr) {
32276 goto suspend;
32277 }
32278 goto label__0__break;
32279 } else {
32280 if (self->private_impl.f_delayed_num_decoded_frames) {
32281 self->private_impl.f_delayed_num_decoded_frames = false;
32282 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
32283 }
Nigel Tao123a5c62022-06-03 14:17:20 +100032284 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100032285 goto label__0__break;
32286 }
32287 }
32288 label__0__break:;
32289
32290 goto ok;
32291 ok:
32292 self->private_impl.p_decode_up_to_id_part1[0] = 0;
32293 goto exit;
32294 }
32295
32296 goto suspend;
32297 suspend:
32298 self->private_impl.p_decode_up_to_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32299
32300 goto exit;
32301 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032302 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032303 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32304 }
32305
32306 return status;
32307}
32308
32309// -------- func gif.decoder.decode_header
32310
32311static wuffs_base__status
32312wuffs_gif__decoder__decode_header(
32313 wuffs_gif__decoder* self,
32314 wuffs_base__io_buffer* a_src) {
32315 wuffs_base__status status = wuffs_base__make_status(NULL);
32316
32317 uint8_t v_c[6] = {0};
32318 uint32_t v_i = 0;
32319
32320 const uint8_t* iop_a_src = NULL;
32321 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32322 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32323 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032324 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032325 io0_a_src = a_src->data.ptr;
32326 io1_a_src = io0_a_src + a_src->meta.ri;
32327 iop_a_src = io1_a_src;
32328 io2_a_src = io0_a_src + a_src->meta.wi;
32329 }
32330
32331 uint32_t coro_susp_point = self->private_impl.p_decode_header[0];
32332 if (coro_susp_point) {
32333 memcpy(v_c, self->private_data.s_decode_header[0].v_c, sizeof(v_c));
32334 v_i = self->private_data.s_decode_header[0].v_i;
32335 }
32336 switch (coro_susp_point) {
32337 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32338
32339 while (v_i < 6) {
32340 {
32341 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32342 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32343 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32344 goto suspend;
32345 }
32346 uint8_t t_0 = *iop_a_src++;
32347 v_c[v_i] = t_0;
32348 }
32349 v_i += 1;
32350 }
32351 if ((v_c[0] != 71) ||
32352 (v_c[1] != 73) ||
32353 (v_c[2] != 70) ||
32354 (v_c[3] != 56) ||
32355 ((v_c[4] != 55) && (v_c[4] != 57)) ||
32356 (v_c[5] != 97)) {
32357 status = wuffs_base__make_status(wuffs_gif__error__bad_header);
32358 goto exit;
32359 }
32360
32361 goto ok;
32362 ok:
32363 self->private_impl.p_decode_header[0] = 0;
32364 goto exit;
32365 }
32366
32367 goto suspend;
32368 suspend:
32369 self->private_impl.p_decode_header[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32370 memcpy(self->private_data.s_decode_header[0].v_c, v_c, sizeof(v_c));
32371 self->private_data.s_decode_header[0].v_i = v_i;
32372
32373 goto exit;
32374 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032375 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032376 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32377 }
32378
32379 return status;
32380}
32381
32382// -------- func gif.decoder.decode_lsd
32383
32384static wuffs_base__status
32385wuffs_gif__decoder__decode_lsd(
32386 wuffs_gif__decoder* self,
32387 wuffs_base__io_buffer* a_src) {
32388 wuffs_base__status status = wuffs_base__make_status(NULL);
32389
32390 uint8_t v_flags = 0;
32391 uint8_t v_background_color_index = 0;
32392 uint32_t v_num_palette_entries = 0;
32393 uint32_t v_i = 0;
32394 uint32_t v_j = 0;
32395 uint32_t v_argb = 0;
32396
32397 const uint8_t* iop_a_src = NULL;
32398 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32399 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32400 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032401 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032402 io0_a_src = a_src->data.ptr;
32403 io1_a_src = io0_a_src + a_src->meta.ri;
32404 iop_a_src = io1_a_src;
32405 io2_a_src = io0_a_src + a_src->meta.wi;
32406 }
32407
32408 uint32_t coro_susp_point = self->private_impl.p_decode_lsd[0];
32409 if (coro_susp_point) {
32410 v_flags = self->private_data.s_decode_lsd[0].v_flags;
32411 v_background_color_index = self->private_data.s_decode_lsd[0].v_background_color_index;
32412 v_num_palette_entries = self->private_data.s_decode_lsd[0].v_num_palette_entries;
32413 v_i = self->private_data.s_decode_lsd[0].v_i;
32414 }
32415 switch (coro_susp_point) {
32416 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32417
32418 {
32419 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32420 uint32_t t_0;
32421 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
32422 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
32423 iop_a_src += 2;
32424 } else {
32425 self->private_data.s_decode_lsd[0].scratch = 0;
32426 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32427 while (true) {
32428 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32429 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32430 goto suspend;
32431 }
32432 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
32433 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
32434 *scratch <<= 8;
32435 *scratch >>= 8;
32436 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
32437 if (num_bits_0 == 8) {
32438 t_0 = ((uint32_t)(*scratch));
32439 break;
32440 }
32441 num_bits_0 += 8;
32442 *scratch |= ((uint64_t)(num_bits_0)) << 56;
32443 }
32444 }
32445 self->private_impl.f_width = t_0;
32446 }
32447 {
32448 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32449 uint32_t t_1;
32450 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
32451 t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
32452 iop_a_src += 2;
32453 } else {
32454 self->private_data.s_decode_lsd[0].scratch = 0;
32455 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
32456 while (true) {
32457 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32458 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32459 goto suspend;
32460 }
32461 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
32462 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
32463 *scratch <<= 8;
32464 *scratch >>= 8;
32465 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
32466 if (num_bits_1 == 8) {
32467 t_1 = ((uint32_t)(*scratch));
32468 break;
32469 }
32470 num_bits_1 += 8;
32471 *scratch |= ((uint64_t)(num_bits_1)) << 56;
32472 }
32473 }
32474 self->private_impl.f_height = t_1;
32475 }
32476 {
32477 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
32478 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32479 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32480 goto suspend;
32481 }
32482 uint8_t t_2 = *iop_a_src++;
32483 v_flags = t_2;
32484 }
32485 {
32486 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
32487 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32488 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32489 goto suspend;
32490 }
32491 uint8_t t_3 = *iop_a_src++;
32492 v_background_color_index = t_3;
32493 }
32494 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
32495 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32496 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32497 goto suspend;
32498 }
32499 iop_a_src++;
32500 v_i = 0;
32501 self->private_impl.f_has_global_palette = ((v_flags & 128) != 0);
32502 if (self->private_impl.f_has_global_palette) {
32503 v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
32504 while (v_i < v_num_palette_entries) {
32505 {
32506 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
32507 uint32_t t_4;
32508 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
32509 t_4 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
32510 iop_a_src += 3;
32511 } else {
32512 self->private_data.s_decode_lsd[0].scratch = 0;
32513 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
32514 while (true) {
32515 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32516 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32517 goto suspend;
32518 }
32519 uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
32520 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
32521 *scratch >>= 8;
32522 *scratch <<= 8;
32523 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
32524 if (num_bits_4 == 16) {
32525 t_4 = ((uint32_t)(*scratch >> 40));
32526 break;
32527 }
32528 num_bits_4 += 8;
32529 *scratch |= ((uint64_t)(num_bits_4));
32530 }
32531 }
32532 v_argb = t_4;
32533 }
32534 v_argb |= 4278190080;
32535 self->private_data.f_palettes[0][((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
32536 self->private_data.f_palettes[0][((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
32537 self->private_data.f_palettes[0][((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
32538 self->private_data.f_palettes[0][((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
32539 v_i += 1;
32540 }
32541 if (self->private_impl.f_quirks[2]) {
32542 if ((v_background_color_index != 0) && (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) {
32543 v_j = (4 * ((uint32_t)(v_background_color_index)));
32544 self->private_impl.f_background_color_u32_argb_premul = ((((uint32_t)(self->private_data.f_palettes[0][(v_j + 0)])) << 0) |
32545 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 1)])) << 8) |
32546 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 2)])) << 16) |
32547 (((uint32_t)(self->private_data.f_palettes[0][(v_j + 3)])) << 24));
32548 } else {
32549 self->private_impl.f_background_color_u32_argb_premul = 77;
32550 }
32551 }
32552 }
32553 while (v_i < 256) {
32554 self->private_data.f_palettes[0][((4 * v_i) + 0)] = 0;
32555 self->private_data.f_palettes[0][((4 * v_i) + 1)] = 0;
32556 self->private_data.f_palettes[0][((4 * v_i) + 2)] = 0;
32557 self->private_data.f_palettes[0][((4 * v_i) + 3)] = 255;
32558 v_i += 1;
32559 }
32560
32561 goto ok;
32562 ok:
32563 self->private_impl.p_decode_lsd[0] = 0;
32564 goto exit;
32565 }
32566
32567 goto suspend;
32568 suspend:
32569 self->private_impl.p_decode_lsd[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32570 self->private_data.s_decode_lsd[0].v_flags = v_flags;
32571 self->private_data.s_decode_lsd[0].v_background_color_index = v_background_color_index;
32572 self->private_data.s_decode_lsd[0].v_num_palette_entries = v_num_palette_entries;
32573 self->private_data.s_decode_lsd[0].v_i = v_i;
32574
32575 goto exit;
32576 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032577 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032578 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32579 }
32580
32581 return status;
32582}
32583
32584// -------- func gif.decoder.decode_extension
32585
32586static wuffs_base__status
32587wuffs_gif__decoder__decode_extension(
32588 wuffs_gif__decoder* self,
32589 wuffs_base__io_buffer* a_src) {
32590 wuffs_base__status status = wuffs_base__make_status(NULL);
32591
32592 uint8_t v_label = 0;
32593
32594 const uint8_t* iop_a_src = NULL;
32595 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32596 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32597 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032598 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032599 io0_a_src = a_src->data.ptr;
32600 io1_a_src = io0_a_src + a_src->meta.ri;
32601 iop_a_src = io1_a_src;
32602 io2_a_src = io0_a_src + a_src->meta.wi;
32603 }
32604
32605 uint32_t coro_susp_point = self->private_impl.p_decode_extension[0];
32606 switch (coro_susp_point) {
32607 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32608
32609 {
32610 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32611 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32612 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32613 goto suspend;
32614 }
32615 uint8_t t_0 = *iop_a_src++;
32616 v_label = t_0;
32617 }
32618 if (v_label == 249) {
32619 if (a_src) {
32620 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32621 }
32622 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32623 status = wuffs_gif__decoder__decode_gc(self, a_src);
32624 if (a_src) {
32625 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32626 }
32627 if (status.repr) {
32628 goto suspend;
32629 }
32630 status = wuffs_base__make_status(NULL);
32631 goto ok;
32632 } else if (v_label == 255) {
32633 if (a_src) {
32634 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32635 }
32636 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32637 status = wuffs_gif__decoder__decode_ae(self, a_src);
32638 if (a_src) {
32639 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32640 }
32641 if (status.repr) {
32642 goto suspend;
32643 }
32644 status = wuffs_base__make_status(NULL);
32645 goto ok;
32646 }
32647 if (a_src) {
32648 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32649 }
32650 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
32651 status = wuffs_gif__decoder__skip_blocks(self, a_src);
32652 if (a_src) {
32653 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32654 }
32655 if (status.repr) {
32656 goto suspend;
32657 }
32658
Nigel Taoe360a532021-04-05 22:47:03 +100032659 ok:
32660 self->private_impl.p_decode_extension[0] = 0;
32661 goto exit;
32662 }
32663
32664 goto suspend;
32665 suspend:
32666 self->private_impl.p_decode_extension[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32667
32668 goto exit;
32669 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032670 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032671 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32672 }
32673
32674 return status;
32675}
32676
32677// -------- func gif.decoder.skip_blocks
32678
32679static wuffs_base__status
32680wuffs_gif__decoder__skip_blocks(
32681 wuffs_gif__decoder* self,
32682 wuffs_base__io_buffer* a_src) {
32683 wuffs_base__status status = wuffs_base__make_status(NULL);
32684
32685 uint8_t v_block_size = 0;
32686
32687 const uint8_t* iop_a_src = NULL;
32688 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32689 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32690 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032691 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032692 io0_a_src = a_src->data.ptr;
32693 io1_a_src = io0_a_src + a_src->meta.ri;
32694 iop_a_src = io1_a_src;
32695 io2_a_src = io0_a_src + a_src->meta.wi;
32696 }
32697
32698 uint32_t coro_susp_point = self->private_impl.p_skip_blocks[0];
32699 switch (coro_susp_point) {
32700 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32701
32702 while (true) {
32703 {
32704 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32705 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32706 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32707 goto suspend;
32708 }
32709 uint8_t t_0 = *iop_a_src++;
32710 v_block_size = t_0;
32711 }
32712 if (v_block_size == 0) {
32713 status = wuffs_base__make_status(NULL);
32714 goto ok;
32715 }
32716 self->private_data.s_skip_blocks[0].scratch = ((uint32_t)(v_block_size));
32717 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32718 if (self->private_data.s_skip_blocks[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
32719 self->private_data.s_skip_blocks[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
32720 iop_a_src = io2_a_src;
32721 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32722 goto suspend;
32723 }
32724 iop_a_src += self->private_data.s_skip_blocks[0].scratch;
32725 }
32726
Nigel Taoe360a532021-04-05 22:47:03 +100032727 ok:
32728 self->private_impl.p_skip_blocks[0] = 0;
32729 goto exit;
32730 }
32731
32732 goto suspend;
32733 suspend:
32734 self->private_impl.p_skip_blocks[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32735
32736 goto exit;
32737 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032738 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032739 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32740 }
32741
32742 return status;
32743}
32744
32745// -------- func gif.decoder.decode_ae
32746
32747static wuffs_base__status
32748wuffs_gif__decoder__decode_ae(
32749 wuffs_gif__decoder* self,
32750 wuffs_base__io_buffer* a_src) {
32751 wuffs_base__status status = wuffs_base__make_status(NULL);
32752
32753 uint8_t v_c = 0;
32754 uint8_t v_block_size = 0;
32755 bool v_is_animexts = false;
32756 bool v_is_netscape = false;
32757 bool v_is_iccp = false;
32758 bool v_is_xmp = false;
32759
32760 const uint8_t* iop_a_src = NULL;
32761 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32762 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32763 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032764 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032765 io0_a_src = a_src->data.ptr;
32766 io1_a_src = io0_a_src + a_src->meta.ri;
32767 iop_a_src = io1_a_src;
32768 io2_a_src = io0_a_src + a_src->meta.wi;
32769 }
32770
32771 uint32_t coro_susp_point = self->private_impl.p_decode_ae[0];
32772 if (coro_susp_point) {
32773 v_block_size = self->private_data.s_decode_ae[0].v_block_size;
32774 v_is_animexts = self->private_data.s_decode_ae[0].v_is_animexts;
32775 v_is_netscape = self->private_data.s_decode_ae[0].v_is_netscape;
32776 v_is_iccp = self->private_data.s_decode_ae[0].v_is_iccp;
32777 v_is_xmp = self->private_data.s_decode_ae[0].v_is_xmp;
32778 }
32779 switch (coro_susp_point) {
32780 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32781
32782 while (true) {
32783 if (self->private_impl.f_metadata_fourcc != 0) {
32784 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
32785 goto ok;
32786 }
32787 {
32788 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32789 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32790 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32791 goto suspend;
32792 }
32793 uint8_t t_0 = *iop_a_src++;
32794 v_block_size = t_0;
32795 }
32796 if (v_block_size == 0) {
32797 status = wuffs_base__make_status(NULL);
32798 goto ok;
32799 }
32800 if (v_block_size != 11) {
32801 self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
32802 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
32803 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
32804 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
32805 iop_a_src = io2_a_src;
32806 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32807 goto suspend;
32808 }
32809 iop_a_src += self->private_data.s_decode_ae[0].scratch;
32810 goto label__goto_done__break;
32811 }
32812 v_is_animexts = true;
32813 v_is_netscape = true;
32814 v_is_iccp = true;
32815 v_is_xmp = true;
32816 v_block_size = 0;
32817 while (v_block_size < 11) {
32818 {
32819 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
32820 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32821 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32822 goto suspend;
32823 }
32824 uint8_t t_1 = *iop_a_src++;
32825 v_c = t_1;
32826 }
32827 v_is_animexts = (v_is_animexts && (v_c == WUFFS_GIF__ANIMEXTS1DOT0[v_block_size]));
32828 v_is_netscape = (v_is_netscape && (v_c == WUFFS_GIF__NETSCAPE2DOT0[v_block_size]));
32829 v_is_iccp = (v_is_iccp && (v_c == WUFFS_GIF__ICCRGBG1012[v_block_size]));
32830 v_is_xmp = (v_is_xmp && (v_c == WUFFS_GIF__XMPDATAXMP[v_block_size]));
32831#if defined(__GNUC__)
32832#pragma GCC diagnostic push
32833#pragma GCC diagnostic ignored "-Wconversion"
32834#endif
32835 v_block_size += 1;
32836#if defined(__GNUC__)
32837#pragma GCC diagnostic pop
32838#endif
32839 }
32840 if (v_is_animexts || v_is_netscape) {
32841 {
32842 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
32843 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32844 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32845 goto suspend;
32846 }
32847 uint8_t t_2 = *iop_a_src++;
32848 v_block_size = t_2;
32849 }
32850 if (v_block_size != 3) {
32851 self->private_data.s_decode_ae[0].scratch = ((uint32_t)(v_block_size));
32852 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
32853 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
32854 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
32855 iop_a_src = io2_a_src;
32856 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32857 goto suspend;
32858 }
32859 iop_a_src += self->private_data.s_decode_ae[0].scratch;
32860 goto label__goto_done__break;
32861 }
32862 {
32863 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
32864 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32865 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32866 goto suspend;
32867 }
32868 uint8_t t_3 = *iop_a_src++;
32869 v_c = t_3;
32870 }
32871 if (v_c != 1) {
32872 self->private_data.s_decode_ae[0].scratch = 2;
32873 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
32874 if (self->private_data.s_decode_ae[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
32875 self->private_data.s_decode_ae[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
32876 iop_a_src = io2_a_src;
32877 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32878 goto suspend;
32879 }
32880 iop_a_src += self->private_data.s_decode_ae[0].scratch;
32881 goto label__goto_done__break;
32882 }
32883 {
32884 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
32885 uint32_t t_4;
32886 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
32887 t_4 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
32888 iop_a_src += 2;
32889 } else {
32890 self->private_data.s_decode_ae[0].scratch = 0;
32891 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
32892 while (true) {
32893 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32894 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32895 goto suspend;
32896 }
32897 uint64_t* scratch = &self->private_data.s_decode_ae[0].scratch;
32898 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
32899 *scratch <<= 8;
32900 *scratch >>= 8;
32901 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
32902 if (num_bits_4 == 8) {
32903 t_4 = ((uint32_t)(*scratch));
32904 break;
32905 }
32906 num_bits_4 += 8;
32907 *scratch |= ((uint64_t)(num_bits_4)) << 56;
32908 }
32909 }
Nigel Taobf9dab32021-11-18 19:19:55 +110032910 self->private_impl.f_num_animation_loops_value = t_4;
Nigel Taoe360a532021-04-05 22:47:03 +100032911 }
Nigel Taobf9dab32021-11-18 19:19:55 +110032912 self->private_impl.f_seen_num_animation_loops_value = true;
32913 if ((0 < self->private_impl.f_num_animation_loops_value) && (self->private_impl.f_num_animation_loops_value <= 65535)) {
32914 self->private_impl.f_num_animation_loops_value += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100032915 }
Nigel Tao123a5c62022-06-03 14:17:20 +100032916 } else if (self->private_impl.f_call_sequence >= 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100032917 } else if (v_is_iccp && self->private_impl.f_report_metadata_iccp) {
32918 self->private_impl.f_metadata_fourcc = 1229144912;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100032919 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 Tao123a5c62022-06-03 14:17:20 +100032920 self->private_impl.f_call_sequence = 16;
Nigel Taoe360a532021-04-05 22:47:03 +100032921 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
32922 goto ok;
32923 } else if (v_is_xmp && self->private_impl.f_report_metadata_xmp) {
32924 self->private_impl.f_metadata_fourcc = 1481461792;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100032925 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 Tao123a5c62022-06-03 14:17:20 +100032926 self->private_impl.f_call_sequence = 16;
Nigel Taoe360a532021-04-05 22:47:03 +100032927 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
32928 goto ok;
32929 }
32930 goto label__goto_done__break;
32931 }
32932 label__goto_done__break:;
32933 if (a_src) {
32934 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32935 }
32936 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
32937 status = wuffs_gif__decoder__skip_blocks(self, a_src);
32938 if (a_src) {
32939 iop_a_src = a_src->data.ptr + a_src->meta.ri;
32940 }
32941 if (status.repr) {
32942 goto suspend;
32943 }
32944
Nigel Taoe360a532021-04-05 22:47:03 +100032945 ok:
32946 self->private_impl.p_decode_ae[0] = 0;
32947 goto exit;
32948 }
32949
32950 goto suspend;
32951 suspend:
32952 self->private_impl.p_decode_ae[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
32953 self->private_data.s_decode_ae[0].v_block_size = v_block_size;
32954 self->private_data.s_decode_ae[0].v_is_animexts = v_is_animexts;
32955 self->private_data.s_decode_ae[0].v_is_netscape = v_is_netscape;
32956 self->private_data.s_decode_ae[0].v_is_iccp = v_is_iccp;
32957 self->private_data.s_decode_ae[0].v_is_xmp = v_is_xmp;
32958
32959 goto exit;
32960 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110032961 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032962 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
32963 }
32964
32965 return status;
32966}
32967
32968// -------- func gif.decoder.decode_gc
32969
32970static wuffs_base__status
32971wuffs_gif__decoder__decode_gc(
32972 wuffs_gif__decoder* self,
32973 wuffs_base__io_buffer* a_src) {
32974 wuffs_base__status status = wuffs_base__make_status(NULL);
32975
32976 uint8_t v_c = 0;
32977 uint8_t v_flags = 0;
32978 uint16_t v_gc_duration_centiseconds = 0;
32979
32980 const uint8_t* iop_a_src = NULL;
32981 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32982 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
32983 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110032984 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100032985 io0_a_src = a_src->data.ptr;
32986 io1_a_src = io0_a_src + a_src->meta.ri;
32987 iop_a_src = io1_a_src;
32988 io2_a_src = io0_a_src + a_src->meta.wi;
32989 }
32990
32991 uint32_t coro_susp_point = self->private_impl.p_decode_gc[0];
32992 switch (coro_susp_point) {
32993 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
32994
32995 {
32996 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
32997 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
32998 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
32999 goto suspend;
33000 }
33001 uint8_t t_0 = *iop_a_src++;
33002 v_c = t_0;
33003 }
33004 if (v_c != 4) {
33005 status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control);
33006 goto exit;
33007 }
33008 {
33009 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
33010 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33011 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33012 goto suspend;
33013 }
33014 uint8_t t_1 = *iop_a_src++;
33015 v_flags = t_1;
33016 }
33017 self->private_impl.f_gc_has_transparent_index = ((v_flags & 1) != 0);
33018 v_flags = ((v_flags >> 2) & 7);
33019 if (v_flags == 2) {
33020 self->private_impl.f_gc_disposal = 1;
33021 } else if ((v_flags == 3) || (v_flags == 4)) {
33022 self->private_impl.f_gc_disposal = 2;
33023 } else {
33024 self->private_impl.f_gc_disposal = 0;
33025 }
33026 {
33027 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
33028 uint16_t t_2;
33029 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
33030 t_2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
33031 iop_a_src += 2;
33032 } else {
33033 self->private_data.s_decode_gc[0].scratch = 0;
33034 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
33035 while (true) {
33036 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33037 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33038 goto suspend;
33039 }
33040 uint64_t* scratch = &self->private_data.s_decode_gc[0].scratch;
33041 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
33042 *scratch <<= 8;
33043 *scratch >>= 8;
33044 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
33045 if (num_bits_2 == 8) {
33046 t_2 = ((uint16_t)(*scratch));
33047 break;
33048 }
33049 num_bits_2 += 8;
33050 *scratch |= ((uint64_t)(num_bits_2)) << 56;
33051 }
33052 }
33053 v_gc_duration_centiseconds = t_2;
33054 }
33055 self->private_impl.f_gc_duration = (((uint64_t)(v_gc_duration_centiseconds)) * 7056000);
33056 {
33057 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
33058 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33059 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33060 goto suspend;
33061 }
33062 uint8_t t_3 = *iop_a_src++;
33063 self->private_impl.f_gc_transparent_index = t_3;
33064 }
33065 {
33066 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
33067 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33068 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33069 goto suspend;
33070 }
33071 uint8_t t_4 = *iop_a_src++;
33072 v_c = t_4;
33073 }
33074 if (v_c != 0) {
33075 status = wuffs_base__make_status(wuffs_gif__error__bad_graphic_control);
33076 goto exit;
33077 }
33078
33079 goto ok;
33080 ok:
33081 self->private_impl.p_decode_gc[0] = 0;
33082 goto exit;
33083 }
33084
33085 goto suspend;
33086 suspend:
33087 self->private_impl.p_decode_gc[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33088
33089 goto exit;
33090 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110033091 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033092 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33093 }
33094
33095 return status;
33096}
33097
33098// -------- func gif.decoder.decode_id_part0
33099
33100static wuffs_base__status
33101wuffs_gif__decoder__decode_id_part0(
33102 wuffs_gif__decoder* self,
33103 wuffs_base__io_buffer* a_src) {
33104 wuffs_base__status status = wuffs_base__make_status(NULL);
33105
33106 const uint8_t* iop_a_src = NULL;
33107 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33108 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33109 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110033110 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033111 io0_a_src = a_src->data.ptr;
33112 io1_a_src = io0_a_src + a_src->meta.ri;
33113 iop_a_src = io1_a_src;
33114 io2_a_src = io0_a_src + a_src->meta.wi;
33115 }
33116
33117 uint32_t coro_susp_point = self->private_impl.p_decode_id_part0[0];
33118 switch (coro_susp_point) {
33119 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33120
33121 {
33122 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
33123 uint32_t t_0;
33124 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
33125 t_0 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
33126 iop_a_src += 2;
33127 } else {
33128 self->private_data.s_decode_id_part0[0].scratch = 0;
33129 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
33130 while (true) {
33131 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33132 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33133 goto suspend;
33134 }
33135 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
33136 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
33137 *scratch <<= 8;
33138 *scratch >>= 8;
33139 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
33140 if (num_bits_0 == 8) {
33141 t_0 = ((uint32_t)(*scratch));
33142 break;
33143 }
33144 num_bits_0 += 8;
33145 *scratch |= ((uint64_t)(num_bits_0)) << 56;
33146 }
33147 }
33148 self->private_impl.f_frame_rect_x0 = t_0;
33149 }
33150 {
33151 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
33152 uint32_t t_1;
33153 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
33154 t_1 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
33155 iop_a_src += 2;
33156 } else {
33157 self->private_data.s_decode_id_part0[0].scratch = 0;
33158 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
33159 while (true) {
33160 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33161 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33162 goto suspend;
33163 }
33164 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
33165 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
33166 *scratch <<= 8;
33167 *scratch >>= 8;
33168 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
33169 if (num_bits_1 == 8) {
33170 t_1 = ((uint32_t)(*scratch));
33171 break;
33172 }
33173 num_bits_1 += 8;
33174 *scratch |= ((uint64_t)(num_bits_1)) << 56;
33175 }
33176 }
33177 self->private_impl.f_frame_rect_y0 = t_1;
33178 }
33179 {
33180 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
33181 uint32_t t_2;
33182 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
33183 t_2 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
33184 iop_a_src += 2;
33185 } else {
33186 self->private_data.s_decode_id_part0[0].scratch = 0;
33187 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
33188 while (true) {
33189 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33190 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33191 goto suspend;
33192 }
33193 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
33194 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
33195 *scratch <<= 8;
33196 *scratch >>= 8;
33197 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
33198 if (num_bits_2 == 8) {
33199 t_2 = ((uint32_t)(*scratch));
33200 break;
33201 }
33202 num_bits_2 += 8;
33203 *scratch |= ((uint64_t)(num_bits_2)) << 56;
33204 }
33205 }
33206 self->private_impl.f_frame_rect_x1 = t_2;
33207 }
33208 self->private_impl.f_frame_rect_x1 += self->private_impl.f_frame_rect_x0;
33209 {
33210 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
33211 uint32_t t_3;
33212 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
33213 t_3 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
33214 iop_a_src += 2;
33215 } else {
33216 self->private_data.s_decode_id_part0[0].scratch = 0;
33217 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
33218 while (true) {
33219 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33220 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33221 goto suspend;
33222 }
33223 uint64_t* scratch = &self->private_data.s_decode_id_part0[0].scratch;
33224 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
33225 *scratch <<= 8;
33226 *scratch >>= 8;
33227 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
33228 if (num_bits_3 == 8) {
33229 t_3 = ((uint32_t)(*scratch));
33230 break;
33231 }
33232 num_bits_3 += 8;
33233 *scratch |= ((uint64_t)(num_bits_3)) << 56;
33234 }
33235 }
33236 self->private_impl.f_frame_rect_y1 = t_3;
33237 }
33238 self->private_impl.f_frame_rect_y1 += self->private_impl.f_frame_rect_y0;
33239 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
33240 self->private_impl.f_dst_y = self->private_impl.f_frame_rect_y0;
Nigel Tao123a5c62022-06-03 14:17:20 +100033241 if ((self->private_impl.f_num_decoded_frame_configs_value == 0) && ! self->private_impl.f_quirks[4]) {
Nigel Taoe360a532021-04-05 22:47:03 +100033242 self->private_impl.f_width = wuffs_base__u32__max(self->private_impl.f_width, self->private_impl.f_frame_rect_x1);
33243 self->private_impl.f_height = wuffs_base__u32__max(self->private_impl.f_height, self->private_impl.f_frame_rect_y1);
33244 }
33245
33246 goto ok;
33247 ok:
33248 self->private_impl.p_decode_id_part0[0] = 0;
33249 goto exit;
33250 }
33251
33252 goto suspend;
33253 suspend:
33254 self->private_impl.p_decode_id_part0[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33255
33256 goto exit;
33257 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110033258 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033259 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33260 }
33261
33262 return status;
33263}
33264
33265// -------- func gif.decoder.decode_id_part1
33266
33267static wuffs_base__status
33268wuffs_gif__decoder__decode_id_part1(
33269 wuffs_gif__decoder* self,
33270 wuffs_base__pixel_buffer* a_dst,
33271 wuffs_base__io_buffer* a_src,
33272 wuffs_base__pixel_blend a_blend) {
33273 wuffs_base__status status = wuffs_base__make_status(NULL);
33274
33275 uint8_t v_flags = 0;
33276 uint8_t v_which_palette = 0;
33277 uint32_t v_num_palette_entries = 0;
33278 uint32_t v_i = 0;
33279 uint32_t v_argb = 0;
33280 wuffs_base__status v_status = wuffs_base__make_status(NULL);
33281 uint8_t v_lw = 0;
33282
33283 const uint8_t* iop_a_src = NULL;
33284 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33285 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33286 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110033287 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033288 io0_a_src = a_src->data.ptr;
33289 io1_a_src = io0_a_src + a_src->meta.ri;
33290 iop_a_src = io1_a_src;
33291 io2_a_src = io0_a_src + a_src->meta.wi;
33292 }
33293
33294 uint32_t coro_susp_point = self->private_impl.p_decode_id_part1[0];
33295 if (coro_susp_point) {
33296 v_which_palette = self->private_data.s_decode_id_part1[0].v_which_palette;
33297 v_num_palette_entries = self->private_data.s_decode_id_part1[0].v_num_palette_entries;
33298 v_i = self->private_data.s_decode_id_part1[0].v_i;
33299 }
33300 switch (coro_susp_point) {
33301 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33302
33303 {
33304 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
33305 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33306 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33307 goto suspend;
33308 }
33309 uint8_t t_0 = *iop_a_src++;
33310 v_flags = t_0;
33311 }
33312 if ((v_flags & 64) != 0) {
33313 self->private_impl.f_interlace = 4;
33314 } else {
33315 self->private_impl.f_interlace = 0;
33316 }
33317 v_which_palette = 1;
33318 if ((v_flags & 128) != 0) {
33319 v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
33320 v_i = 0;
33321 while (v_i < v_num_palette_entries) {
33322 {
33323 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
33324 uint32_t t_1;
33325 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
33326 t_1 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
33327 iop_a_src += 3;
33328 } else {
33329 self->private_data.s_decode_id_part1[0].scratch = 0;
33330 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
33331 while (true) {
33332 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33333 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33334 goto suspend;
33335 }
33336 uint64_t* scratch = &self->private_data.s_decode_id_part1[0].scratch;
33337 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
33338 *scratch >>= 8;
33339 *scratch <<= 8;
33340 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
33341 if (num_bits_1 == 16) {
33342 t_1 = ((uint32_t)(*scratch >> 40));
33343 break;
33344 }
33345 num_bits_1 += 8;
33346 *scratch |= ((uint64_t)(num_bits_1));
33347 }
33348 }
33349 v_argb = t_1;
33350 }
33351 v_argb |= 4278190080;
33352 self->private_data.f_palettes[1][((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
33353 self->private_data.f_palettes[1][((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
33354 self->private_data.f_palettes[1][((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
33355 self->private_data.f_palettes[1][((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
33356 v_i += 1;
33357 }
33358 while (v_i < 256) {
33359 self->private_data.f_palettes[1][((4 * v_i) + 0)] = 0;
33360 self->private_data.f_palettes[1][((4 * v_i) + 1)] = 0;
33361 self->private_data.f_palettes[1][((4 * v_i) + 2)] = 0;
33362 self->private_data.f_palettes[1][((4 * v_i) + 3)] = 255;
33363 v_i += 1;
33364 }
33365 } else if (self->private_impl.f_quirks[6] && ! self->private_impl.f_has_global_palette) {
33366 status = wuffs_base__make_status(wuffs_gif__error__bad_palette);
33367 goto exit;
33368 } else if (self->private_impl.f_gc_has_transparent_index) {
33369 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));
33370 } else {
33371 v_which_palette = 0;
33372 }
33373 if (self->private_impl.f_gc_has_transparent_index) {
33374 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 0)] = 0;
33375 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 1)] = 0;
33376 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 2)] = 0;
33377 self->private_data.f_palettes[1][((4 * ((uint32_t)(self->private_impl.f_gc_transparent_index))) + 3)] = 0;
33378 }
33379 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
33380 wuffs_base__pixel_buffer__pixel_format(a_dst),
33381 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)),
33382 wuffs_base__utility__make_pixel_format(2198077448),
33383 wuffs_base__make_slice_u8(self->private_data.f_palettes[v_which_palette], 1024),
33384 a_blend);
33385 if ( ! wuffs_base__status__is_ok(&v_status)) {
33386 status = v_status;
33387 if (wuffs_base__status__is_error(&status)) {
33388 goto exit;
33389 } else if (wuffs_base__status__is_suspension(&status)) {
33390 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
33391 goto exit;
33392 }
33393 goto ok;
33394 }
33395 if (self->private_impl.f_previous_lzw_decode_ended_abruptly) {
Nigel Taobf9dab32021-11-18 19:19:55 +110033396 wuffs_base__ignore_status(wuffs_lzw__decoder__initialize(&self->private_data.f_lzw,
33397 sizeof (wuffs_lzw__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
Nigel Taoe360a532021-04-05 22:47:03 +100033398 }
33399 {
33400 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
33401 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33402 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33403 goto suspend;
33404 }
33405 uint8_t t_2 = *iop_a_src++;
33406 v_lw = t_2;
33407 }
33408 if (v_lw > 8) {
33409 status = wuffs_base__make_status(wuffs_gif__error__bad_literal_width);
33410 goto exit;
33411 }
33412 wuffs_lzw__decoder__set_literal_width(&self->private_data.f_lzw, ((uint32_t)(v_lw)));
33413 self->private_impl.f_previous_lzw_decode_ended_abruptly = true;
33414
Nigel Taoe360a532021-04-05 22:47:03 +100033415 ok:
33416 self->private_impl.p_decode_id_part1[0] = 0;
33417 goto exit;
33418 }
33419
33420 goto suspend;
33421 suspend:
33422 self->private_impl.p_decode_id_part1[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33423 self->private_data.s_decode_id_part1[0].v_which_palette = v_which_palette;
33424 self->private_data.s_decode_id_part1[0].v_num_palette_entries = v_num_palette_entries;
33425 self->private_data.s_decode_id_part1[0].v_i = v_i;
33426
33427 goto exit;
33428 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110033429 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033430 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33431 }
33432
33433 return status;
33434}
33435
33436// -------- func gif.decoder.decode_id_part2
33437
33438static wuffs_base__status
33439wuffs_gif__decoder__decode_id_part2(
33440 wuffs_gif__decoder* self,
33441 wuffs_base__pixel_buffer* a_dst,
33442 wuffs_base__io_buffer* a_src,
33443 wuffs_base__slice_u8 a_workbuf) {
33444 wuffs_base__io_buffer empty_io_buffer = wuffs_base__empty_io_buffer();
33445
33446 wuffs_base__status status = wuffs_base__make_status(NULL);
33447
33448 uint64_t v_block_size = 0;
33449 bool v_need_block_size = false;
33450 uint32_t v_n_copied = 0;
33451 uint64_t v_n_compressed = 0;
33452 wuffs_base__io_buffer u_r = wuffs_base__empty_io_buffer();
33453 wuffs_base__io_buffer* v_r = &u_r;
33454 const uint8_t* iop_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33455 const uint8_t* io0_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33456 const uint8_t* io1_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33457 const uint8_t* io2_v_r WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33458 uint64_t v_mark = 0;
33459 wuffs_base__status v_lzw_status = wuffs_base__make_status(NULL);
33460 wuffs_base__status v_copy_status = wuffs_base__make_status(NULL);
33461 wuffs_base__slice_u8 v_uncompressed = {0};
33462
33463 const uint8_t* iop_a_src = NULL;
33464 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33465 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33466 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110033467 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033468 io0_a_src = a_src->data.ptr;
33469 io1_a_src = io0_a_src + a_src->meta.ri;
33470 iop_a_src = io1_a_src;
33471 io2_a_src = io0_a_src + a_src->meta.wi;
33472 }
33473
33474 uint32_t coro_susp_point = self->private_impl.p_decode_id_part2[0];
33475 if (coro_susp_point) {
33476 v_block_size = self->private_data.s_decode_id_part2[0].v_block_size;
33477 v_need_block_size = self->private_data.s_decode_id_part2[0].v_need_block_size;
Nigel Taoe360a532021-04-05 22:47:03 +100033478 }
33479 switch (coro_susp_point) {
33480 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
33481
33482 v_need_block_size = true;
33483 label__outer__continue:;
33484 while (true) {
33485 if (v_need_block_size) {
33486 v_need_block_size = false;
33487 {
33488 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
33489 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
33490 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33491 goto suspend;
33492 }
33493 uint64_t t_0 = *iop_a_src++;
33494 v_block_size = t_0;
33495 }
33496 }
33497 if (v_block_size == 0) {
33498 goto label__outer__break;
33499 }
33500 while (((uint64_t)(io2_a_src - iop_a_src)) == 0) {
33501 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33502 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
33503 }
33504 if (self->private_impl.f_compressed_ri == self->private_impl.f_compressed_wi) {
33505 self->private_impl.f_compressed_ri = 0;
33506 self->private_impl.f_compressed_wi = 0;
33507 }
33508 while (self->private_impl.f_compressed_wi <= 3841) {
33509 v_n_compressed = wuffs_base__u64__min(v_block_size, ((uint64_t)(io2_a_src - iop_a_src)));
33510 if (v_n_compressed <= 0) {
33511 goto label__0__break;
33512 }
33513 v_n_copied = wuffs_base__io_reader__limited_copy_u32_to_slice(
Nigel Tao123a5c62022-06-03 14:17:20 +100033514 &iop_a_src, io2_a_src,((uint32_t)((v_n_compressed & 4294967295))), wuffs_base__make_slice_u8_ij(self->private_data.f_compressed, self->private_impl.f_compressed_wi, 4096));
Nigel Taoe360a532021-04-05 22:47:03 +100033515 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_compressed_wi, ((uint64_t)(v_n_copied)));
33516 wuffs_base__u64__sat_sub_indirect(&v_block_size, ((uint64_t)(v_n_copied)));
33517 if (v_block_size > 0) {
33518 goto label__0__break;
33519 }
33520 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
33521 v_need_block_size = true;
33522 goto label__0__break;
33523 }
33524 v_block_size = ((uint64_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src)));
33525 iop_a_src += 1;
33526 }
33527 label__0__break:;
33528 label__inner__continue:;
33529 while (true) {
33530 if ((self->private_impl.f_compressed_ri > self->private_impl.f_compressed_wi) || (self->private_impl.f_compressed_wi > 4096)) {
33531 status = wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
33532 goto exit;
33533 }
33534 {
33535 wuffs_base__io_buffer* o_0_v_r = v_r;
33536 const uint8_t *o_0_iop_v_r = iop_v_r;
33537 const uint8_t *o_0_io0_v_r = io0_v_r;
33538 const uint8_t *o_0_io1_v_r = io1_v_r;
33539 const uint8_t *o_0_io2_v_r = io2_v_r;
33540 v_r = wuffs_base__io_reader__set(
33541 &u_r,
33542 &iop_v_r,
33543 &io0_v_r,
33544 &io1_v_r,
33545 &io2_v_r,
Nigel Tao123a5c62022-06-03 14:17:20 +100033546 wuffs_base__make_slice_u8_ij(self->private_data.f_compressed,
Nigel Taoe360a532021-04-05 22:47:03 +100033547 self->private_impl.f_compressed_ri,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100033548 self->private_impl.f_compressed_wi),
33549 0);
Nigel Taoe360a532021-04-05 22:47:03 +100033550 v_mark = ((uint64_t)(iop_v_r - io0_v_r));
33551 {
33552 u_r.meta.ri = ((size_t)(iop_v_r - u_r.data.ptr));
33553 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());
33554 v_lzw_status = t_1;
33555 iop_v_r = u_r.data.ptr + u_r.meta.ri;
33556 }
33557 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))));
33558 v_r = o_0_v_r;
33559 iop_v_r = o_0_iop_v_r;
33560 io0_v_r = o_0_io0_v_r;
33561 io1_v_r = o_0_io1_v_r;
33562 io2_v_r = o_0_io2_v_r;
33563 }
33564 v_uncompressed = wuffs_lzw__decoder__flush(&self->private_data.f_lzw);
33565 if (((uint64_t)(v_uncompressed.len)) > 0) {
33566 v_copy_status = wuffs_gif__decoder__copy_to_image_buffer(self, a_dst, v_uncompressed);
33567 if (wuffs_base__status__is_error(&v_copy_status)) {
33568 status = v_copy_status;
33569 goto exit;
33570 }
33571 }
33572 if (wuffs_base__status__is_ok(&v_lzw_status)) {
33573 self->private_impl.f_previous_lzw_decode_ended_abruptly = false;
33574 if (v_need_block_size || (v_block_size > 0)) {
33575 self->private_data.s_decode_id_part2[0].scratch = ((uint32_t)(v_block_size));
33576 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
33577 if (self->private_data.s_decode_id_part2[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
33578 self->private_data.s_decode_id_part2[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
33579 iop_a_src = io2_a_src;
33580 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33581 goto suspend;
33582 }
33583 iop_a_src += self->private_data.s_decode_id_part2[0].scratch;
33584 if (a_src) {
33585 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33586 }
33587 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
33588 status = wuffs_gif__decoder__skip_blocks(self, a_src);
33589 if (a_src) {
33590 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33591 }
33592 if (status.repr) {
33593 goto suspend;
33594 }
33595 }
33596 goto label__outer__break;
33597 } else if (v_lzw_status.repr == wuffs_base__suspension__short_read) {
33598 goto label__outer__continue;
33599 } else if (v_lzw_status.repr == wuffs_base__suspension__short_write) {
33600 goto label__inner__continue;
Nigel Taoa0e24542021-11-19 14:05:40 +110033601 } else if (self->private_impl.f_quirks[3] && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) && (self->private_impl.f_interlace == 0)) {
33602 if (v_need_block_size || (v_block_size > 0)) {
33603 self->private_data.s_decode_id_part2[0].scratch = ((uint32_t)(v_block_size));
33604 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
33605 if (self->private_data.s_decode_id_part2[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
33606 self->private_data.s_decode_id_part2[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
33607 iop_a_src = io2_a_src;
33608 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
33609 goto suspend;
33610 }
33611 iop_a_src += self->private_data.s_decode_id_part2[0].scratch;
33612 if (a_src) {
33613 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33614 }
33615 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
33616 status = wuffs_gif__decoder__skip_blocks(self, a_src);
33617 if (a_src) {
33618 iop_a_src = a_src->data.ptr + a_src->meta.ri;
33619 }
33620 if (status.repr) {
33621 goto suspend;
33622 }
33623 }
33624 goto label__outer__break;
Nigel Taoe360a532021-04-05 22:47:03 +100033625 }
33626 status = v_lzw_status;
33627 if (wuffs_base__status__is_error(&status)) {
33628 goto exit;
33629 } else if (wuffs_base__status__is_suspension(&status)) {
33630 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
33631 goto exit;
33632 }
33633 goto ok;
33634 }
33635 }
33636 label__outer__break:;
33637 self->private_impl.f_compressed_ri = 0;
33638 self->private_impl.f_compressed_wi = 0;
33639 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)) {
33640 status = wuffs_base__make_status(wuffs_base__error__not_enough_data);
33641 goto exit;
33642 }
33643
Nigel Taoe360a532021-04-05 22:47:03 +100033644 ok:
33645 self->private_impl.p_decode_id_part2[0] = 0;
33646 goto exit;
33647 }
33648
33649 goto suspend;
33650 suspend:
33651 self->private_impl.p_decode_id_part2[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
33652 self->private_data.s_decode_id_part2[0].v_block_size = v_block_size;
33653 self->private_data.s_decode_id_part2[0].v_need_block_size = v_need_block_size;
Nigel Taoe360a532021-04-05 22:47:03 +100033654
33655 goto exit;
33656 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110033657 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033658 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
33659 }
33660
33661 return status;
33662}
33663
33664// -------- func gif.decoder.copy_to_image_buffer
33665
33666static wuffs_base__status
33667wuffs_gif__decoder__copy_to_image_buffer(
33668 wuffs_gif__decoder* self,
33669 wuffs_base__pixel_buffer* a_pb,
33670 wuffs_base__slice_u8 a_src) {
33671 wuffs_base__slice_u8 v_dst = {0};
33672 wuffs_base__slice_u8 v_src = {0};
33673 uint64_t v_width_in_bytes = 0;
33674 uint64_t v_n = 0;
33675 uint64_t v_src_ri = 0;
33676 wuffs_base__pixel_format v_pixfmt = {0};
33677 uint32_t v_bytes_per_pixel = 0;
33678 uint32_t v_bits_per_pixel = 0;
33679 wuffs_base__table_u8 v_tab = {0};
33680 uint64_t v_i = 0;
33681 uint64_t v_j = 0;
33682 uint32_t v_replicate_y0 = 0;
33683 uint32_t v_replicate_y1 = 0;
33684 wuffs_base__slice_u8 v_replicate_dst = {0};
33685 wuffs_base__slice_u8 v_replicate_src = {0};
33686
33687 v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb);
33688 v_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_pixfmt);
33689 if ((v_bits_per_pixel & 7) != 0) {
33690 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
33691 }
33692 v_bytes_per_pixel = (v_bits_per_pixel >> 3);
33693 v_width_in_bytes = (((uint64_t)(self->private_impl.f_width)) * ((uint64_t)(v_bytes_per_pixel)));
33694 v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0);
33695 label__0__continue:;
33696 while (v_src_ri < ((uint64_t)(a_src.len))) {
33697 v_src = wuffs_base__slice_u8__subslice_i(a_src, v_src_ri);
33698 if (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1) {
33699 if (self->private_impl.f_quirks[3]) {
33700 return wuffs_base__make_status(NULL);
33701 }
33702 return wuffs_base__make_status(wuffs_base__error__too_much_data);
33703 }
Nigel Taobf9dab32021-11-18 19:19:55 +110033704 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100033705 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
33706 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, 0);
33707 } else if (v_width_in_bytes < ((uint64_t)(v_dst.len))) {
33708 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_width_in_bytes);
33709 }
33710 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * ((uint64_t)(v_bytes_per_pixel)));
33711 if (v_i < ((uint64_t)(v_dst.len))) {
33712 v_j = (((uint64_t)(self->private_impl.f_frame_rect_x1)) * ((uint64_t)(v_bytes_per_pixel)));
33713 if ((v_i <= v_j) && (v_j <= ((uint64_t)(v_dst.len)))) {
33714 v_dst = wuffs_base__slice_u8__subslice_ij(v_dst, v_i, v_j);
33715 } else {
33716 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_i);
33717 }
33718 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);
33719 wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n);
33720 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
33721 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));
33722 }
33723 if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) {
33724 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
33725 if (self->private_impl.f_interlace == 0) {
33726 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, 1);
33727 goto label__0__continue;
33728 }
33729 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 +110033730 v_replicate_src = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100033731 v_replicate_y0 = wuffs_base__u32__sat_add(self->private_impl.f_dst_y, 1);
33732 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])));
33733 v_replicate_y1 = wuffs_base__u32__min(v_replicate_y1, self->private_impl.f_frame_rect_y1);
33734 while (v_replicate_y0 < v_replicate_y1) {
Nigel Taobf9dab32021-11-18 19:19:55 +110033735 v_replicate_dst = wuffs_base__table_u8__row_u32(v_tab, v_replicate_y0);
Nigel Taoe360a532021-04-05 22:47:03 +100033736 wuffs_base__slice_u8__copy_from_slice(v_replicate_dst, v_replicate_src);
33737 v_replicate_y0 += 1;
33738 }
33739 self->private_impl.f_dirty_max_excl_y = wuffs_base__u32__max(self->private_impl.f_dirty_max_excl_y, v_replicate_y1);
33740 }
33741 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace])));
33742 while ((self->private_impl.f_interlace > 0) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) {
33743#if defined(__GNUC__)
33744#pragma GCC diagnostic push
33745#pragma GCC diagnostic ignored "-Wconversion"
33746#endif
33747 self->private_impl.f_interlace -= 1;
33748#if defined(__GNUC__)
33749#pragma GCC diagnostic pop
33750#endif
33751 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]);
33752 }
33753 goto label__0__continue;
33754 }
33755 if (((uint64_t)(a_src.len)) == v_src_ri) {
33756 goto label__0__break;
33757 } else if (((uint64_t)(a_src.len)) < v_src_ri) {
33758 return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
33759 }
33760 v_n = ((uint64_t)((self->private_impl.f_frame_rect_x1 - self->private_impl.f_dst_x)));
33761 v_n = wuffs_base__u64__min(v_n, (((uint64_t)(a_src.len)) - v_src_ri));
33762 wuffs_base__u64__sat_add_indirect(&v_src_ri, v_n);
33763 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
33764 if (self->private_impl.f_frame_rect_x1 <= self->private_impl.f_dst_x) {
33765 self->private_impl.f_dst_x = self->private_impl.f_frame_rect_x0;
33766 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_y, ((uint32_t)(WUFFS_GIF__INTERLACE_DELTA[self->private_impl.f_interlace])));
33767 while ((self->private_impl.f_interlace > 0) && (self->private_impl.f_dst_y >= self->private_impl.f_frame_rect_y1)) {
33768#if defined(__GNUC__)
33769#pragma GCC diagnostic push
33770#pragma GCC diagnostic ignored "-Wconversion"
33771#endif
33772 self->private_impl.f_interlace -= 1;
33773#if defined(__GNUC__)
33774#pragma GCC diagnostic pop
33775#endif
33776 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]);
33777 }
33778 goto label__0__continue;
33779 }
33780 if (v_src_ri != ((uint64_t)(a_src.len))) {
33781 return wuffs_base__make_status(wuffs_gif__error__internal_error_inconsistent_ri_wi);
33782 }
33783 goto label__0__break;
33784 }
33785 label__0__break:;
33786 return wuffs_base__make_status(NULL);
33787}
33788
33789#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
33790
33791#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP)
33792
33793// ---------------- Status Codes Implementations
33794
33795const char wuffs_gzip__error__bad_checksum[] = "#gzip: bad checksum";
33796const char wuffs_gzip__error__bad_compression_method[] = "#gzip: bad compression method";
33797const char wuffs_gzip__error__bad_encoding_flags[] = "#gzip: bad encoding flags";
33798const char wuffs_gzip__error__bad_header[] = "#gzip: bad header";
33799
33800// ---------------- Private Consts
33801
33802// ---------------- Private Initializer Prototypes
33803
33804// ---------------- Private Function Prototypes
33805
33806// ---------------- VTables
33807
33808const wuffs_base__io_transformer__func_ptrs
33809wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer = {
33810 (wuffs_base__empty_struct(*)(void*,
33811 uint32_t,
33812 bool))(&wuffs_gzip__decoder__set_quirk_enabled),
33813 (wuffs_base__status(*)(void*,
33814 wuffs_base__io_buffer*,
33815 wuffs_base__io_buffer*,
33816 wuffs_base__slice_u8))(&wuffs_gzip__decoder__transform_io),
33817 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_gzip__decoder__workbuf_len),
33818};
33819
33820// ---------------- Initializer Implementations
33821
33822wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
33823wuffs_gzip__decoder__initialize(
33824 wuffs_gzip__decoder* self,
33825 size_t sizeof_star_self,
33826 uint64_t wuffs_version,
33827 uint32_t options){
33828 if (!self) {
33829 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
33830 }
33831 if (sizeof(*self) != sizeof_star_self) {
33832 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
33833 }
33834 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
33835 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
33836 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
33837 }
33838
33839 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
33840 // The whole point of this if-check is to detect an uninitialized *self.
33841 // We disable the warning on GCC. Clang-5.0 does not have this warning.
33842#if !defined(__clang__) && defined(__GNUC__)
33843#pragma GCC diagnostic push
33844#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
33845#endif
33846 if (self->private_impl.magic != 0) {
33847 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
33848 }
33849#if !defined(__clang__) && defined(__GNUC__)
33850#pragma GCC diagnostic pop
33851#endif
33852 } else {
33853 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
33854 memset(self, 0, sizeof(*self));
33855 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
33856 } else {
33857 memset(&(self->private_impl), 0, sizeof(self->private_impl));
33858 }
33859 }
33860
33861 {
33862 wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize(
33863 &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options);
33864 if (z.repr) {
33865 return z;
33866 }
33867 }
33868 {
33869 wuffs_base__status z = wuffs_deflate__decoder__initialize(
33870 &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options);
33871 if (z.repr) {
33872 return z;
33873 }
33874 }
33875 self->private_impl.magic = WUFFS_BASE__MAGIC;
33876 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
33877 wuffs_base__io_transformer__vtable_name;
33878 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
33879 (const void*)(&wuffs_gzip__decoder__func_ptrs_for__wuffs_base__io_transformer);
33880 return wuffs_base__make_status(NULL);
33881}
33882
33883wuffs_gzip__decoder*
33884wuffs_gzip__decoder__alloc() {
33885 wuffs_gzip__decoder* x =
33886 (wuffs_gzip__decoder*)(calloc(sizeof(wuffs_gzip__decoder), 1));
33887 if (!x) {
33888 return NULL;
33889 }
33890 if (wuffs_gzip__decoder__initialize(
33891 x, sizeof(wuffs_gzip__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
33892 free(x);
33893 return NULL;
33894 }
33895 return x;
33896}
33897
33898size_t
33899sizeof__wuffs_gzip__decoder() {
33900 return sizeof(wuffs_gzip__decoder);
33901}
33902
33903// ---------------- Function Implementations
33904
33905// -------- func gzip.decoder.set_quirk_enabled
33906
33907WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
33908wuffs_gzip__decoder__set_quirk_enabled(
33909 wuffs_gzip__decoder* self,
33910 uint32_t a_quirk,
33911 bool a_enabled) {
33912 if (!self) {
33913 return wuffs_base__make_empty_struct();
33914 }
33915 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
33916 return wuffs_base__make_empty_struct();
33917 }
33918
33919 if (a_quirk == 1) {
33920 self->private_impl.f_ignore_checksum = a_enabled;
33921 }
33922 return wuffs_base__make_empty_struct();
33923}
33924
33925// -------- func gzip.decoder.workbuf_len
33926
33927WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
33928wuffs_gzip__decoder__workbuf_len(
33929 const wuffs_gzip__decoder* self) {
33930 if (!self) {
33931 return wuffs_base__utility__empty_range_ii_u64();
33932 }
33933 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
33934 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
33935 return wuffs_base__utility__empty_range_ii_u64();
33936 }
33937
33938 return wuffs_base__utility__make_range_ii_u64(1, 1);
33939}
33940
33941// -------- func gzip.decoder.transform_io
33942
33943WUFFS_BASE__MAYBE_STATIC wuffs_base__status
33944wuffs_gzip__decoder__transform_io(
33945 wuffs_gzip__decoder* self,
33946 wuffs_base__io_buffer* a_dst,
33947 wuffs_base__io_buffer* a_src,
33948 wuffs_base__slice_u8 a_workbuf) {
33949 if (!self) {
33950 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
33951 }
33952 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
33953 return wuffs_base__make_status(
33954 (self->private_impl.magic == WUFFS_BASE__DISABLED)
33955 ? wuffs_base__error__disabled_by_previous_error
33956 : wuffs_base__error__initialize_not_called);
33957 }
33958 if (!a_dst || !a_src) {
33959 self->private_impl.magic = WUFFS_BASE__DISABLED;
33960 return wuffs_base__make_status(wuffs_base__error__bad_argument);
33961 }
33962 if ((self->private_impl.active_coroutine != 0) &&
33963 (self->private_impl.active_coroutine != 1)) {
33964 self->private_impl.magic = WUFFS_BASE__DISABLED;
33965 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
33966 }
33967 self->private_impl.active_coroutine = 0;
33968 wuffs_base__status status = wuffs_base__make_status(NULL);
33969
33970 uint8_t v_c = 0;
33971 uint8_t v_flags = 0;
33972 uint16_t v_xlen = 0;
33973 uint64_t v_mark = 0;
33974 uint32_t v_checksum_got = 0;
33975 uint32_t v_decoded_length_got = 0;
33976 wuffs_base__status v_status = wuffs_base__make_status(NULL);
33977 uint32_t v_checksum_want = 0;
33978 uint32_t v_decoded_length_want = 0;
33979
33980 uint8_t* iop_a_dst = NULL;
33981 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33982 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33983 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110033984 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033985 io0_a_dst = a_dst->data.ptr;
33986 io1_a_dst = io0_a_dst + a_dst->meta.wi;
33987 iop_a_dst = io1_a_dst;
33988 io2_a_dst = io0_a_dst + a_dst->data.len;
33989 if (a_dst->meta.closed) {
33990 io2_a_dst = iop_a_dst;
33991 }
33992 }
33993 const uint8_t* iop_a_src = NULL;
33994 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33995 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
33996 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110033997 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100033998 io0_a_src = a_src->data.ptr;
33999 io1_a_src = io0_a_src + a_src->meta.ri;
34000 iop_a_src = io1_a_src;
34001 io2_a_src = io0_a_src + a_src->meta.wi;
34002 }
34003
34004 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
34005 if (coro_susp_point) {
34006 v_flags = self->private_data.s_transform_io[0].v_flags;
34007 v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
34008 v_decoded_length_got = self->private_data.s_transform_io[0].v_decoded_length_got;
34009 v_checksum_want = self->private_data.s_transform_io[0].v_checksum_want;
34010 }
34011 switch (coro_susp_point) {
34012 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
34013
34014 {
34015 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
34016 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34017 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34018 goto suspend;
34019 }
34020 uint8_t t_0 = *iop_a_src++;
34021 v_c = t_0;
34022 }
34023 if (v_c != 31) {
34024 status = wuffs_base__make_status(wuffs_gzip__error__bad_header);
34025 goto exit;
34026 }
34027 {
34028 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
34029 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34030 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34031 goto suspend;
34032 }
34033 uint8_t t_1 = *iop_a_src++;
34034 v_c = t_1;
34035 }
34036 if (v_c != 139) {
34037 status = wuffs_base__make_status(wuffs_gzip__error__bad_header);
34038 goto exit;
34039 }
34040 {
34041 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
34042 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34043 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34044 goto suspend;
34045 }
34046 uint8_t t_2 = *iop_a_src++;
34047 v_c = t_2;
34048 }
34049 if (v_c != 8) {
34050 status = wuffs_base__make_status(wuffs_gzip__error__bad_compression_method);
34051 goto exit;
34052 }
34053 {
34054 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
34055 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34056 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34057 goto suspend;
34058 }
34059 uint8_t t_3 = *iop_a_src++;
34060 v_flags = t_3;
34061 }
34062 self->private_data.s_transform_io[0].scratch = 6;
34063 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
34064 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
34065 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
34066 iop_a_src = io2_a_src;
34067 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34068 goto suspend;
34069 }
34070 iop_a_src += self->private_data.s_transform_io[0].scratch;
34071 if ((v_flags & 4) != 0) {
34072 {
34073 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
34074 uint16_t t_4;
34075 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
34076 t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
34077 iop_a_src += 2;
34078 } else {
34079 self->private_data.s_transform_io[0].scratch = 0;
34080 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
34081 while (true) {
34082 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34083 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34084 goto suspend;
34085 }
34086 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
34087 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
34088 *scratch <<= 8;
34089 *scratch >>= 8;
34090 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
34091 if (num_bits_4 == 8) {
34092 t_4 = ((uint16_t)(*scratch));
34093 break;
34094 }
34095 num_bits_4 += 8;
34096 *scratch |= ((uint64_t)(num_bits_4)) << 56;
34097 }
34098 }
34099 v_xlen = t_4;
34100 }
34101 self->private_data.s_transform_io[0].scratch = ((uint32_t)(v_xlen));
34102 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
34103 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
34104 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
34105 iop_a_src = io2_a_src;
34106 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34107 goto suspend;
34108 }
34109 iop_a_src += self->private_data.s_transform_io[0].scratch;
34110 }
34111 if ((v_flags & 8) != 0) {
34112 while (true) {
34113 {
34114 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
34115 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34116 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34117 goto suspend;
34118 }
34119 uint8_t t_5 = *iop_a_src++;
34120 v_c = t_5;
34121 }
34122 if (v_c == 0) {
34123 goto label__0__break;
34124 }
34125 }
34126 label__0__break:;
34127 }
34128 if ((v_flags & 16) != 0) {
34129 while (true) {
34130 {
34131 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
34132 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34133 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34134 goto suspend;
34135 }
34136 uint8_t t_6 = *iop_a_src++;
34137 v_c = t_6;
34138 }
34139 if (v_c == 0) {
34140 goto label__1__break;
34141 }
34142 }
34143 label__1__break:;
34144 }
34145 if ((v_flags & 2) != 0) {
34146 self->private_data.s_transform_io[0].scratch = 2;
34147 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
34148 if (self->private_data.s_transform_io[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
34149 self->private_data.s_transform_io[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
34150 iop_a_src = io2_a_src;
34151 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34152 goto suspend;
34153 }
34154 iop_a_src += self->private_data.s_transform_io[0].scratch;
34155 }
34156 if ((v_flags & 224) != 0) {
34157 status = wuffs_base__make_status(wuffs_gzip__error__bad_encoding_flags);
34158 goto exit;
34159 }
34160 while (true) {
34161 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
34162 {
34163 if (a_dst) {
34164 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
34165 }
34166 if (a_src) {
34167 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34168 }
34169 wuffs_base__status t_7 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf);
34170 v_status = t_7;
34171 if (a_dst) {
34172 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
34173 }
34174 if (a_src) {
34175 iop_a_src = a_src->data.ptr + a_src->meta.ri;
34176 }
34177 }
34178 if ( ! self->private_impl.f_ignore_checksum) {
34179 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));
34180 v_decoded_length_got += ((uint32_t)((wuffs_base__io__count_since(v_mark, ((uint64_t)(iop_a_dst - io0_a_dst))) & 4294967295)));
34181 }
34182 if (wuffs_base__status__is_ok(&v_status)) {
34183 goto label__2__break;
34184 }
34185 status = v_status;
34186 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
34187 }
34188 label__2__break:;
34189 {
34190 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
34191 uint32_t t_8;
34192 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34193 t_8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34194 iop_a_src += 4;
34195 } else {
34196 self->private_data.s_transform_io[0].scratch = 0;
34197 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
34198 while (true) {
34199 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34200 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34201 goto suspend;
34202 }
34203 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
34204 uint32_t num_bits_8 = ((uint32_t)(*scratch >> 56));
34205 *scratch <<= 8;
34206 *scratch >>= 8;
34207 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_8;
34208 if (num_bits_8 == 24) {
34209 t_8 = ((uint32_t)(*scratch));
34210 break;
34211 }
34212 num_bits_8 += 8;
34213 *scratch |= ((uint64_t)(num_bits_8)) << 56;
34214 }
34215 }
34216 v_checksum_want = t_8;
34217 }
34218 {
34219 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
34220 uint32_t t_9;
34221 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
34222 t_9 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34223 iop_a_src += 4;
34224 } else {
34225 self->private_data.s_transform_io[0].scratch = 0;
34226 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
34227 while (true) {
34228 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
34229 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34230 goto suspend;
34231 }
34232 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
34233 uint32_t num_bits_9 = ((uint32_t)(*scratch >> 56));
34234 *scratch <<= 8;
34235 *scratch >>= 8;
34236 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_9;
34237 if (num_bits_9 == 24) {
34238 t_9 = ((uint32_t)(*scratch));
34239 break;
34240 }
34241 num_bits_9 += 8;
34242 *scratch |= ((uint64_t)(num_bits_9)) << 56;
34243 }
34244 }
34245 v_decoded_length_want = t_9;
34246 }
34247 if ( ! self->private_impl.f_ignore_checksum && ((v_checksum_got != v_checksum_want) || (v_decoded_length_got != v_decoded_length_want))) {
34248 status = wuffs_base__make_status(wuffs_gzip__error__bad_checksum);
34249 goto exit;
34250 }
34251
Nigel Taoe360a532021-04-05 22:47:03 +100034252 ok:
34253 self->private_impl.p_transform_io[0] = 0;
34254 goto exit;
34255 }
34256
34257 goto suspend;
34258 suspend:
34259 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
34260 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
34261 self->private_data.s_transform_io[0].v_flags = v_flags;
34262 self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
34263 self->private_data.s_transform_io[0].v_decoded_length_got = v_decoded_length_got;
34264 self->private_data.s_transform_io[0].v_checksum_want = v_checksum_want;
34265
34266 goto exit;
34267 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110034268 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100034269 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
34270 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110034271 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100034272 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34273 }
34274
34275 if (wuffs_base__status__is_error(&status)) {
34276 self->private_impl.magic = WUFFS_BASE__DISABLED;
34277 }
34278 return status;
34279}
34280
34281#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GZIP)
34282
34283#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON)
34284
34285// ---------------- Status Codes Implementations
34286
34287const char wuffs_json__error__bad_c0_control_code[] = "#json: bad C0 control code";
34288const char wuffs_json__error__bad_utf_8[] = "#json: bad UTF-8";
34289const char wuffs_json__error__bad_backslash_escape[] = "#json: bad backslash-escape";
34290const char wuffs_json__error__bad_input[] = "#json: bad input";
34291const char wuffs_json__error__bad_new_line_in_a_string[] = "#json: bad new-line in a string";
34292const char wuffs_json__error__bad_quirk_combination[] = "#json: bad quirk combination";
34293const char wuffs_json__error__unsupported_number_length[] = "#json: unsupported number length";
34294const char wuffs_json__error__unsupported_recursion_depth[] = "#json: unsupported recursion depth";
34295const char wuffs_json__error__internal_error_inconsistent_i_o[] = "#json: internal error: inconsistent I/O";
34296
34297// ---------------- Private Consts
34298
34299#define WUFFS_JSON__DECODER_NUMBER_LENGTH_MAX_INCL 99
34300
34301static const uint8_t
34302WUFFS_JSON__LUT_BACKSLASHES[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
34303 0, 0, 0, 0, 0, 0, 0, 0,
34304 0, 0, 3, 0, 0, 0, 0, 0,
34305 0, 0, 0, 0, 0, 0, 0, 0,
34306 0, 0, 0, 0, 0, 0, 0, 0,
34307 0, 0, 162, 0, 0, 0, 0, 5,
34308 0, 0, 0, 0, 0, 0, 0, 175,
34309 7, 0, 0, 0, 0, 0, 0, 0,
34310 0, 0, 0, 0, 0, 0, 0, 4,
34311 0, 0, 0, 0, 0, 0, 0, 0,
34312 0, 0, 0, 0, 0, 0, 0, 0,
34313 0, 0, 0, 0, 0, 0, 0, 0,
34314 0, 0, 0, 0, 220, 0, 0, 0,
34315 0, 1, 136, 0, 0, 2, 140, 0,
34316 0, 0, 0, 0, 0, 0, 138, 0,
34317 0, 0, 141, 0, 137, 0, 6, 0,
34318 0, 0, 0, 0, 0, 0, 0, 0,
34319 0, 0, 0, 0, 0, 0, 0, 0,
34320 0, 0, 0, 0, 0, 0, 0, 0,
34321 0, 0, 0, 0, 0, 0, 0, 0,
34322 0, 0, 0, 0, 0, 0, 0, 0,
34323 0, 0, 0, 0, 0, 0, 0, 0,
34324 0, 0, 0, 0, 0, 0, 0, 0,
34325 0, 0, 0, 0, 0, 0, 0, 0,
34326 0, 0, 0, 0, 0, 0, 0, 0,
34327 0, 0, 0, 0, 0, 0, 0, 0,
34328 0, 0, 0, 0, 0, 0, 0, 0,
34329 0, 0, 0, 0, 0, 0, 0, 0,
34330 0, 0, 0, 0, 0, 0, 0, 0,
34331 0, 0, 0, 0, 0, 0, 0, 0,
34332 0, 0, 0, 0, 0, 0, 0, 0,
34333 0, 0, 0, 0, 0, 0, 0, 0,
34334 0, 0, 0, 0, 0, 0, 0, 0,
34335};
34336
34337static const uint8_t
34338WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
34339 0, 1, 3, 4, 5, 6, 7, 10,
34340};
34341
34342static const uint8_t
34343WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
34344 0, 7, 27, 10, 63, 39, 11, 0,
34345};
34346
34347static const uint8_t
34348WUFFS_JSON__LUT_CHARS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
34349 128, 129, 130, 131, 132, 133, 134, 135,
34350 136, 137, 138, 139, 140, 141, 142, 143,
34351 144, 145, 146, 147, 148, 149, 150, 151,
34352 152, 153, 154, 155, 156, 157, 158, 159,
34353 0, 0, 1, 0, 0, 0, 0, 0,
34354 0, 0, 0, 0, 0, 0, 0, 0,
34355 0, 0, 0, 0, 0, 0, 0, 0,
34356 0, 0, 0, 0, 0, 0, 0, 0,
34357 0, 0, 0, 0, 0, 0, 0, 0,
34358 0, 0, 0, 0, 0, 0, 0, 0,
34359 0, 0, 0, 0, 0, 0, 0, 0,
34360 0, 0, 0, 0, 2, 0, 0, 0,
34361 0, 0, 0, 0, 0, 0, 0, 0,
34362 0, 0, 0, 0, 0, 0, 0, 0,
34363 0, 0, 0, 0, 0, 0, 0, 0,
34364 0, 0, 0, 0, 0, 0, 0, 0,
34365 16, 16, 16, 16, 16, 16, 16, 16,
34366 16, 16, 16, 16, 16, 16, 16, 16,
34367 16, 16, 16, 16, 16, 16, 16, 16,
34368 16, 16, 16, 16, 16, 16, 16, 16,
34369 16, 16, 16, 16, 16, 16, 16, 16,
34370 16, 16, 16, 16, 16, 16, 16, 16,
34371 16, 16, 16, 16, 16, 16, 16, 16,
34372 16, 16, 16, 16, 16, 16, 16, 16,
34373 32, 32, 3, 3, 3, 3, 3, 3,
34374 3, 3, 3, 3, 3, 3, 3, 3,
34375 3, 3, 3, 3, 3, 3, 3, 3,
34376 3, 3, 3, 3, 3, 3, 3, 3,
34377 4, 4, 4, 4, 4, 4, 4, 4,
34378 4, 4, 4, 4, 4, 4, 4, 4,
34379 5, 5, 5, 5, 5, 32, 32, 32,
34380 32, 32, 32, 32, 32, 32, 32, 32,
34381};
34382
34383#define WUFFS_JSON__CLASS_WHITESPACE 0
34384
34385#define WUFFS_JSON__CLASS_STRING 1
34386
34387#define WUFFS_JSON__CLASS_COMMA 2
34388
34389#define WUFFS_JSON__CLASS_COLON 3
34390
34391#define WUFFS_JSON__CLASS_NUMBER 4
34392
34393#define WUFFS_JSON__CLASS_OPEN_CURLY_BRACE 5
34394
34395#define WUFFS_JSON__CLASS_CLOSE_CURLY_BRACE 6
34396
34397#define WUFFS_JSON__CLASS_OPEN_SQUARE_BRACKET 7
34398
34399#define WUFFS_JSON__CLASS_CLOSE_SQUARE_BRACKET 8
34400
34401#define WUFFS_JSON__CLASS_FALSE 9
34402
34403#define WUFFS_JSON__CLASS_TRUE 10
34404
34405#define WUFFS_JSON__CLASS_NULL_NAN_INF 11
34406
34407#define WUFFS_JSON__CLASS_COMMENT 12
34408
34409#define WUFFS_JSON__EXPECT_VALUE 7858
34410
34411#define WUFFS_JSON__EXPECT_NON_STRING_VALUE 7856
34412
34413#define WUFFS_JSON__EXPECT_STRING 4098
34414
34415#define WUFFS_JSON__EXPECT_COMMA 4100
34416
34417#define WUFFS_JSON__EXPECT_COLON 4104
34418
34419#define WUFFS_JSON__EXPECT_NUMBER 4112
34420
34421#define WUFFS_JSON__EXPECT_CLOSE_CURLY_BRACE 4160
34422
34423#define WUFFS_JSON__EXPECT_CLOSE_SQUARE_BRACKET 4352
34424
34425static const uint8_t
34426WUFFS_JSON__LUT_CLASSES[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
34427 15, 15, 15, 15, 15, 15, 15, 15,
34428 15, 0, 0, 15, 15, 0, 15, 15,
34429 15, 15, 15, 15, 15, 15, 15, 15,
34430 15, 15, 15, 15, 15, 15, 15, 15,
34431 0, 15, 1, 15, 15, 15, 15, 15,
34432 15, 15, 15, 11, 2, 4, 15, 12,
34433 4, 4, 4, 4, 4, 4, 4, 4,
34434 4, 4, 3, 15, 15, 15, 15, 15,
34435 15, 15, 15, 15, 15, 15, 15, 15,
34436 15, 11, 15, 15, 15, 15, 11, 15,
34437 15, 15, 15, 15, 15, 15, 15, 15,
34438 15, 15, 15, 7, 15, 8, 15, 15,
34439 15, 15, 15, 15, 15, 15, 9, 15,
34440 15, 11, 15, 15, 15, 15, 11, 15,
34441 15, 15, 15, 15, 10, 15, 15, 15,
34442 15, 15, 15, 5, 15, 6, 15, 15,
34443 15, 15, 15, 15, 15, 15, 15, 15,
34444 15, 15, 15, 15, 15, 15, 15, 15,
34445 15, 15, 15, 15, 15, 15, 15, 15,
34446 15, 15, 15, 15, 15, 15, 15, 15,
34447 15, 15, 15, 15, 15, 15, 15, 15,
34448 15, 15, 15, 15, 15, 15, 15, 15,
34449 15, 15, 15, 15, 15, 15, 15, 15,
34450 15, 15, 15, 15, 15, 15, 15, 15,
34451 15, 15, 15, 15, 15, 15, 15, 15,
34452 15, 15, 15, 15, 15, 15, 15, 15,
34453 15, 15, 15, 15, 15, 15, 15, 15,
34454 15, 15, 15, 15, 15, 15, 15, 15,
34455 15, 15, 15, 15, 15, 15, 15, 15,
34456 15, 15, 15, 15, 15, 15, 15, 15,
34457 15, 15, 15, 15, 15, 15, 15, 15,
34458 15, 15, 15, 15, 15, 15, 15, 15,
34459};
34460
34461static const uint8_t
34462WUFFS_JSON__LUT_DECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
34463 0, 0, 0, 0, 0, 0, 0, 0,
34464 0, 0, 0, 0, 0, 0, 0, 0,
34465 0, 0, 0, 0, 0, 0, 0, 0,
34466 0, 0, 0, 0, 0, 0, 0, 0,
34467 0, 0, 0, 0, 0, 0, 0, 0,
34468 0, 0, 0, 0, 0, 0, 0, 0,
34469 128, 129, 130, 131, 132, 133, 134, 135,
34470 136, 137, 0, 0, 0, 0, 0, 0,
34471 0, 0, 0, 0, 0, 0, 0, 0,
34472 0, 0, 0, 0, 0, 0, 0, 0,
34473 0, 0, 0, 0, 0, 0, 0, 0,
34474 0, 0, 0, 0, 0, 0, 0, 0,
34475 0, 0, 0, 0, 0, 0, 0, 0,
34476 0, 0, 0, 0, 0, 0, 0, 0,
34477 0, 0, 0, 0, 0, 0, 0, 0,
34478 0, 0, 0, 0, 0, 0, 0, 0,
34479 0, 0, 0, 0, 0, 0, 0, 0,
34480 0, 0, 0, 0, 0, 0, 0, 0,
34481 0, 0, 0, 0, 0, 0, 0, 0,
34482 0, 0, 0, 0, 0, 0, 0, 0,
34483 0, 0, 0, 0, 0, 0, 0, 0,
34484 0, 0, 0, 0, 0, 0, 0, 0,
34485 0, 0, 0, 0, 0, 0, 0, 0,
34486 0, 0, 0, 0, 0, 0, 0, 0,
34487 0, 0, 0, 0, 0, 0, 0, 0,
34488 0, 0, 0, 0, 0, 0, 0, 0,
34489 0, 0, 0, 0, 0, 0, 0, 0,
34490 0, 0, 0, 0, 0, 0, 0, 0,
34491 0, 0, 0, 0, 0, 0, 0, 0,
34492 0, 0, 0, 0, 0, 0, 0, 0,
34493 0, 0, 0, 0, 0, 0, 0, 0,
34494 0, 0, 0, 0, 0, 0, 0, 0,
34495};
34496
34497static const uint8_t
34498WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
34499 0, 0, 0, 0, 0, 0, 0, 0,
34500 0, 0, 0, 0, 0, 0, 0, 0,
34501 0, 0, 0, 0, 0, 0, 0, 0,
34502 0, 0, 0, 0, 0, 0, 0, 0,
34503 0, 0, 0, 0, 0, 0, 0, 0,
34504 0, 0, 0, 0, 0, 0, 0, 0,
34505 128, 129, 130, 131, 132, 133, 134, 135,
34506 136, 137, 0, 0, 0, 0, 0, 0,
34507 0, 138, 139, 140, 141, 142, 143, 0,
34508 0, 0, 0, 0, 0, 0, 0, 0,
34509 0, 0, 0, 0, 0, 0, 0, 0,
34510 0, 0, 0, 0, 0, 0, 0, 0,
34511 0, 138, 139, 140, 141, 142, 143, 0,
34512 0, 0, 0, 0, 0, 0, 0, 0,
34513 0, 0, 0, 0, 0, 0, 0, 0,
34514 0, 0, 0, 0, 0, 0, 0, 0,
34515 0, 0, 0, 0, 0, 0, 0, 0,
34516 0, 0, 0, 0, 0, 0, 0, 0,
34517 0, 0, 0, 0, 0, 0, 0, 0,
34518 0, 0, 0, 0, 0, 0, 0, 0,
34519 0, 0, 0, 0, 0, 0, 0, 0,
34520 0, 0, 0, 0, 0, 0, 0, 0,
34521 0, 0, 0, 0, 0, 0, 0, 0,
34522 0, 0, 0, 0, 0, 0, 0, 0,
34523 0, 0, 0, 0, 0, 0, 0, 0,
34524 0, 0, 0, 0, 0, 0, 0, 0,
34525 0, 0, 0, 0, 0, 0, 0, 0,
34526 0, 0, 0, 0, 0, 0, 0, 0,
34527 0, 0, 0, 0, 0, 0, 0, 0,
34528 0, 0, 0, 0, 0, 0, 0, 0,
34529 0, 0, 0, 0, 0, 0, 0, 0,
34530 0, 0, 0, 0, 0, 0, 0, 0,
34531};
34532
34533#define WUFFS_JSON__QUIRKS_BASE 1225364480
34534
34535#define WUFFS_JSON__QUIRKS_COUNT 21
34536
34537// ---------------- Private Initializer Prototypes
34538
34539// ---------------- Private Function Prototypes
34540
34541static uint32_t
34542wuffs_json__decoder__decode_number(
34543 wuffs_json__decoder* self,
34544 wuffs_base__io_buffer* a_src);
34545
34546static uint32_t
34547wuffs_json__decoder__decode_digits(
34548 wuffs_json__decoder* self,
34549 wuffs_base__io_buffer* a_src,
34550 uint32_t a_n);
34551
34552static wuffs_base__status
34553wuffs_json__decoder__decode_leading(
34554 wuffs_json__decoder* self,
34555 wuffs_base__token_buffer* a_dst,
34556 wuffs_base__io_buffer* a_src);
34557
34558static wuffs_base__status
34559wuffs_json__decoder__decode_comment(
34560 wuffs_json__decoder* self,
34561 wuffs_base__token_buffer* a_dst,
34562 wuffs_base__io_buffer* a_src);
34563
34564static wuffs_base__status
34565wuffs_json__decoder__decode_inf_nan(
34566 wuffs_json__decoder* self,
34567 wuffs_base__token_buffer* a_dst,
34568 wuffs_base__io_buffer* a_src);
34569
34570static wuffs_base__status
34571wuffs_json__decoder__decode_trailer(
34572 wuffs_json__decoder* self,
34573 wuffs_base__token_buffer* a_dst,
34574 wuffs_base__io_buffer* a_src);
34575
34576// ---------------- VTables
34577
34578const wuffs_base__token_decoder__func_ptrs
34579wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder = {
34580 (wuffs_base__status(*)(void*,
34581 wuffs_base__token_buffer*,
34582 wuffs_base__io_buffer*,
34583 wuffs_base__slice_u8))(&wuffs_json__decoder__decode_tokens),
34584 (wuffs_base__empty_struct(*)(void*,
34585 uint32_t,
34586 bool))(&wuffs_json__decoder__set_quirk_enabled),
34587 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_json__decoder__workbuf_len),
34588};
34589
34590// ---------------- Initializer Implementations
34591
34592wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
34593wuffs_json__decoder__initialize(
34594 wuffs_json__decoder* self,
34595 size_t sizeof_star_self,
34596 uint64_t wuffs_version,
34597 uint32_t options){
34598 if (!self) {
34599 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34600 }
34601 if (sizeof(*self) != sizeof_star_self) {
34602 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
34603 }
34604 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
34605 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
34606 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
34607 }
34608
34609 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
34610 // The whole point of this if-check is to detect an uninitialized *self.
34611 // We disable the warning on GCC. Clang-5.0 does not have this warning.
34612#if !defined(__clang__) && defined(__GNUC__)
34613#pragma GCC diagnostic push
34614#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
34615#endif
34616 if (self->private_impl.magic != 0) {
34617 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
34618 }
34619#if !defined(__clang__) && defined(__GNUC__)
34620#pragma GCC diagnostic pop
34621#endif
34622 } else {
34623 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
34624 memset(self, 0, sizeof(*self));
34625 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
34626 } else {
34627 memset(&(self->private_impl), 0, sizeof(self->private_impl));
34628 }
34629 }
34630
34631 self->private_impl.magic = WUFFS_BASE__MAGIC;
34632 self->private_impl.vtable_for__wuffs_base__token_decoder.vtable_name =
34633 wuffs_base__token_decoder__vtable_name;
34634 self->private_impl.vtable_for__wuffs_base__token_decoder.function_pointers =
34635 (const void*)(&wuffs_json__decoder__func_ptrs_for__wuffs_base__token_decoder);
34636 return wuffs_base__make_status(NULL);
34637}
34638
34639wuffs_json__decoder*
34640wuffs_json__decoder__alloc() {
34641 wuffs_json__decoder* x =
34642 (wuffs_json__decoder*)(calloc(sizeof(wuffs_json__decoder), 1));
34643 if (!x) {
34644 return NULL;
34645 }
34646 if (wuffs_json__decoder__initialize(
34647 x, sizeof(wuffs_json__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
34648 free(x);
34649 return NULL;
34650 }
34651 return x;
34652}
34653
34654size_t
34655sizeof__wuffs_json__decoder() {
34656 return sizeof(wuffs_json__decoder);
34657}
34658
34659// ---------------- Function Implementations
34660
34661// -------- func json.decoder.set_quirk_enabled
34662
34663WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
34664wuffs_json__decoder__set_quirk_enabled(
34665 wuffs_json__decoder* self,
34666 uint32_t a_quirk,
34667 bool a_enabled) {
34668 if (!self) {
34669 return wuffs_base__make_empty_struct();
34670 }
34671 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34672 return wuffs_base__make_empty_struct();
34673 }
34674
34675 if (a_quirk >= 1225364480) {
34676 a_quirk -= 1225364480;
34677 if (a_quirk < 21) {
34678 self->private_impl.f_quirks[a_quirk] = a_enabled;
34679 }
34680 }
34681 return wuffs_base__make_empty_struct();
34682}
34683
34684// -------- func json.decoder.workbuf_len
34685
34686WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
34687wuffs_json__decoder__workbuf_len(
34688 const wuffs_json__decoder* self) {
34689 if (!self) {
34690 return wuffs_base__utility__empty_range_ii_u64();
34691 }
34692 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
34693 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
34694 return wuffs_base__utility__empty_range_ii_u64();
34695 }
34696
34697 return wuffs_base__utility__empty_range_ii_u64();
34698}
34699
34700// -------- func json.decoder.decode_tokens
34701
34702WUFFS_BASE__MAYBE_STATIC wuffs_base__status
34703wuffs_json__decoder__decode_tokens(
34704 wuffs_json__decoder* self,
34705 wuffs_base__token_buffer* a_dst,
34706 wuffs_base__io_buffer* a_src,
34707 wuffs_base__slice_u8 a_workbuf) {
34708 if (!self) {
34709 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
34710 }
34711 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
34712 return wuffs_base__make_status(
34713 (self->private_impl.magic == WUFFS_BASE__DISABLED)
34714 ? wuffs_base__error__disabled_by_previous_error
34715 : wuffs_base__error__initialize_not_called);
34716 }
34717 if (!a_dst || !a_src) {
34718 self->private_impl.magic = WUFFS_BASE__DISABLED;
34719 return wuffs_base__make_status(wuffs_base__error__bad_argument);
34720 }
34721 if ((self->private_impl.active_coroutine != 0) &&
34722 (self->private_impl.active_coroutine != 1)) {
34723 self->private_impl.magic = WUFFS_BASE__DISABLED;
34724 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
34725 }
34726 self->private_impl.active_coroutine = 0;
34727 wuffs_base__status status = wuffs_base__make_status(NULL);
34728
34729 uint32_t v_vminor = 0;
34730 uint32_t v_number_length = 0;
34731 uint32_t v_number_status = 0;
34732 uint32_t v_string_length = 0;
34733 uint32_t v_whitespace_length = 0;
34734 uint32_t v_depth = 0;
34735 uint32_t v_stack_byte = 0;
34736 uint32_t v_stack_bit = 0;
34737 uint32_t v_match = 0;
34738 uint32_t v_c4 = 0;
34739 uint8_t v_c = 0;
34740 uint8_t v_backslash = 0;
34741 uint8_t v_char = 0;
34742 uint8_t v_class = 0;
34743 uint32_t v_multi_byte_utf8 = 0;
34744 uint8_t v_backslash_x_ok = 0;
34745 uint8_t v_backslash_x_value = 0;
34746 uint32_t v_backslash_x_string = 0;
34747 uint8_t v_uni4_ok = 0;
34748 uint64_t v_uni4_string = 0;
34749 uint32_t v_uni4_value = 0;
34750 uint32_t v_uni4_high_surrogate = 0;
34751 uint8_t v_uni8_ok = 0;
34752 uint64_t v_uni8_string = 0;
34753 uint32_t v_uni8_value = 0;
34754 uint32_t v_expect = 0;
34755 uint32_t v_expect_after_value = 0;
34756
34757 wuffs_base__token* iop_a_dst = NULL;
34758 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34759 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34760 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110034761 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100034762 io0_a_dst = a_dst->data.ptr;
34763 io1_a_dst = io0_a_dst + a_dst->meta.wi;
34764 iop_a_dst = io1_a_dst;
34765 io2_a_dst = io0_a_dst + a_dst->data.len;
34766 if (a_dst->meta.closed) {
34767 io2_a_dst = iop_a_dst;
34768 }
34769 }
34770 const uint8_t* iop_a_src = NULL;
34771 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34772 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
34773 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110034774 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100034775 io0_a_src = a_src->data.ptr;
34776 io1_a_src = io0_a_src + a_src->meta.ri;
34777 iop_a_src = io1_a_src;
34778 io2_a_src = io0_a_src + a_src->meta.wi;
34779 }
34780
34781 uint32_t coro_susp_point = self->private_impl.p_decode_tokens[0];
34782 if (coro_susp_point) {
34783 v_depth = self->private_data.s_decode_tokens[0].v_depth;
34784 v_expect = self->private_data.s_decode_tokens[0].v_expect;
34785 v_expect_after_value = self->private_data.s_decode_tokens[0].v_expect_after_value;
34786 }
34787 switch (coro_susp_point) {
34788 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
34789
34790 if (self->private_impl.f_end_of_data) {
34791 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
34792 goto ok;
34793 }
34794 if (self->private_impl.f_quirks[18]) {
34795 if (self->private_impl.f_quirks[11] || self->private_impl.f_quirks[12] || self->private_impl.f_quirks[17]) {
34796 status = wuffs_base__make_status(wuffs_json__error__bad_quirk_combination);
34797 goto exit;
34798 }
34799 }
34800 if (self->private_impl.f_quirks[15] || self->private_impl.f_quirks[16]) {
34801 if (a_dst) {
34802 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
34803 }
34804 if (a_src) {
34805 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
34806 }
34807 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
34808 status = wuffs_json__decoder__decode_leading(self, a_dst, a_src);
34809 if (a_dst) {
34810 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
34811 }
34812 if (a_src) {
34813 iop_a_src = a_src->data.ptr + a_src->meta.ri;
34814 }
34815 if (status.repr) {
34816 goto suspend;
34817 }
34818 }
34819 v_expect = 7858;
34820 label__outer__continue:;
34821 while (true) {
34822 while (true) {
34823 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
34824 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
34825 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
34826 goto label__outer__continue;
34827 }
34828 v_whitespace_length = 0;
34829 v_c = 0;
34830 v_class = 0;
34831 while (true) {
34832 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
34833 if (v_whitespace_length > 0) {
34834 *iop_a_dst++ = wuffs_base__make_token(
34835 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34836 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34837 v_whitespace_length = 0;
34838 }
34839 if (a_src && a_src->meta.closed) {
34840 status = wuffs_base__make_status(wuffs_json__error__bad_input);
34841 goto exit;
34842 }
34843 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34844 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
Nigel Taoe360a532021-04-05 22:47:03 +100034845 goto label__outer__continue;
34846 }
34847 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
34848 v_class = WUFFS_JSON__LUT_CLASSES[v_c];
34849 if (v_class != 0) {
34850 goto label__ws__break;
34851 }
34852 iop_a_src += 1;
34853 if (v_whitespace_length >= 65534) {
34854 *iop_a_dst++ = wuffs_base__make_token(
34855 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34856 (((uint64_t)(65535)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34857 v_whitespace_length = 0;
34858 goto label__outer__continue;
34859 }
34860 v_whitespace_length += 1;
34861 }
34862 label__ws__break:;
34863 if (v_whitespace_length > 0) {
34864 *iop_a_dst++ = wuffs_base__make_token(
34865 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34866 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34867 v_whitespace_length = 0;
34868 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
34869 goto label__outer__continue;
34870 }
34871 }
34872 if (0 == (v_expect & (((uint32_t)(1)) << v_class))) {
34873 status = wuffs_base__make_status(wuffs_json__error__bad_input);
34874 goto exit;
34875 }
34876 if (v_class == 1) {
34877 *iop_a_dst++ = wuffs_base__make_token(
34878 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34879 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34880 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34881 iop_a_src += 1;
34882 label__string_loop_outer__continue:;
34883 while (true) {
34884 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
34885 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
34886 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
34887 goto label__string_loop_outer__continue;
34888 }
34889 v_string_length = 0;
34890 label__string_loop_inner__continue:;
34891 while (true) {
34892 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
34893 if (v_string_length > 0) {
34894 *iop_a_dst++ = wuffs_base__make_token(
34895 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34896 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34897 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34898 v_string_length = 0;
34899 }
34900 if (a_src && a_src->meta.closed) {
34901 status = wuffs_base__make_status(wuffs_json__error__bad_input);
34902 goto exit;
34903 }
34904 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34905 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
Nigel Taoe360a532021-04-05 22:47:03 +100034906 goto label__string_loop_outer__continue;
34907 }
34908 while (((uint64_t)(io2_a_src - iop_a_src)) > 4) {
34909 v_c4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
34910 if (0 != (WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 0))] |
34911 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 8))] |
34912 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 16))] |
34913 WUFFS_JSON__LUT_CHARS[(255 & (v_c4 >> 24))])) {
34914 goto label__0__break;
34915 }
34916 iop_a_src += 4;
34917 if (v_string_length > 65527) {
34918 *iop_a_dst++ = wuffs_base__make_token(
34919 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34920 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34921 (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34922 v_string_length = 0;
34923 goto label__string_loop_outer__continue;
34924 }
34925 v_string_length += 4;
34926 }
34927 label__0__break:;
34928 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
34929 v_char = WUFFS_JSON__LUT_CHARS[v_c];
34930 if (v_char == 0) {
34931 iop_a_src += 1;
34932 if (v_string_length >= 65531) {
34933 *iop_a_dst++ = wuffs_base__make_token(
34934 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34935 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34936 (((uint64_t)(65532)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34937 v_string_length = 0;
34938 goto label__string_loop_outer__continue;
34939 }
34940 v_string_length += 1;
34941 goto label__string_loop_inner__continue;
34942 } else if (v_char == 1) {
34943 if (v_string_length != 0) {
34944 *iop_a_dst++ = wuffs_base__make_token(
34945 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34946 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34947 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34948 v_string_length = 0;
34949 }
34950 goto label__string_loop_outer__break;
34951 } else if (v_char == 2) {
34952 if (v_string_length > 0) {
34953 *iop_a_dst++ = wuffs_base__make_token(
34954 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34955 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34956 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34957 v_string_length = 0;
34958 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
34959 goto label__string_loop_outer__continue;
34960 }
34961 }
34962 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
34963 if (a_src && a_src->meta.closed) {
34964 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
34965 goto exit;
34966 }
34967 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34968 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
Nigel Taoe360a532021-04-05 22:47:03 +100034969 goto label__string_loop_outer__continue;
34970 }
34971 v_c = ((uint8_t)((wuffs_base__peek_u16le__no_bounds_check(iop_a_src) >> 8)));
34972 v_backslash = WUFFS_JSON__LUT_BACKSLASHES[v_c];
34973 if ((v_backslash & 128) != 0) {
34974 iop_a_src += 2;
34975 *iop_a_dst++ = wuffs_base__make_token(
34976 (((uint64_t)((6291456 | ((uint32_t)((v_backslash & 127)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34977 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34978 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34979 goto label__string_loop_outer__continue;
34980 } else if (v_backslash != 0) {
34981 if (self->private_impl.f_quirks[WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_QUIRKS[(v_backslash & 7)]]) {
34982 iop_a_src += 2;
34983 *iop_a_dst++ = wuffs_base__make_token(
34984 (((uint64_t)((6291456 | ((uint32_t)(WUFFS_JSON__LUT_QUIRKY_BACKSLASHES_CHARS[(v_backslash & 7)]))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
34985 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
34986 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
34987 goto label__string_loop_outer__continue;
34988 }
34989 } else if (v_c == 117) {
34990 if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
34991 if (a_src && a_src->meta.closed) {
34992 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
34993 goto exit;
34994 }
34995 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
34996 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
Nigel Taoe360a532021-04-05 22:47:03 +100034997 goto label__string_loop_outer__continue;
34998 }
34999 v_uni4_string = (((uint64_t)(wuffs_base__peek_u48le__no_bounds_check(iop_a_src))) >> 16);
35000 v_uni4_value = 0;
35001 v_uni4_ok = 128;
35002 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 0))];
35003 v_uni4_ok &= v_c;
35004 v_uni4_value |= (((uint32_t)((v_c & 15))) << 12);
35005 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 8))];
35006 v_uni4_ok &= v_c;
35007 v_uni4_value |= (((uint32_t)((v_c & 15))) << 8);
35008 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 16))];
35009 v_uni4_ok &= v_c;
35010 v_uni4_value |= (((uint32_t)((v_c & 15))) << 4);
35011 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 24))];
35012 v_uni4_ok &= v_c;
35013 v_uni4_value |= (((uint32_t)((v_c & 15))) << 0);
35014 if (v_uni4_ok == 0) {
35015 } else if ((v_uni4_value < 55296) || (57343 < v_uni4_value)) {
35016 iop_a_src += 6;
35017 *iop_a_dst++ = wuffs_base__make_token(
35018 (((uint64_t)((6291456 | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35019 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35020 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35021 goto label__string_loop_outer__continue;
35022 } else if (v_uni4_value >= 56320) {
35023 } else {
35024 if (((uint64_t)(io2_a_src - iop_a_src)) < 12) {
35025 if (a_src && a_src->meta.closed) {
35026 if (self->private_impl.f_quirks[20]) {
35027 iop_a_src += 6;
35028 *iop_a_dst++ = wuffs_base__make_token(
35029 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35030 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35031 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35032 goto label__string_loop_outer__continue;
35033 }
35034 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
35035 goto exit;
35036 }
35037 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35038 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
Nigel Taoe360a532021-04-05 22:47:03 +100035039 goto label__string_loop_outer__continue;
35040 }
35041 v_uni4_string = (wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 4) >> 16);
35042 if (((255 & (v_uni4_string >> 0)) != 92) || ((255 & (v_uni4_string >> 8)) != 117)) {
35043 v_uni4_high_surrogate = 0;
35044 v_uni4_value = 0;
35045 v_uni4_ok = 0;
35046 } else {
35047 v_uni4_high_surrogate = (65536 + ((v_uni4_value - 55296) << 10));
35048 v_uni4_value = 0;
35049 v_uni4_ok = 128;
35050 v_uni4_string >>= 16;
35051 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 0))];
35052 v_uni4_ok &= v_c;
35053 v_uni4_value |= (((uint32_t)((v_c & 15))) << 12);
35054 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 8))];
35055 v_uni4_ok &= v_c;
35056 v_uni4_value |= (((uint32_t)((v_c & 15))) << 8);
35057 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 16))];
35058 v_uni4_ok &= v_c;
35059 v_uni4_value |= (((uint32_t)((v_c & 15))) << 4);
35060 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni4_string >> 24))];
35061 v_uni4_ok &= v_c;
35062 v_uni4_value |= (((uint32_t)((v_c & 15))) << 0);
35063 }
35064 if ((v_uni4_ok != 0) && (56320 <= v_uni4_value) && (v_uni4_value <= 57343)) {
35065 v_uni4_value -= 56320;
35066 iop_a_src += 12;
35067 *iop_a_dst++ = wuffs_base__make_token(
35068 (((uint64_t)((6291456 | v_uni4_high_surrogate | v_uni4_value))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35069 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35070 (((uint64_t)(12)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35071 goto label__string_loop_outer__continue;
35072 }
35073 }
35074 if (self->private_impl.f_quirks[20]) {
35075 if (((uint64_t)(io2_a_src - iop_a_src)) < 6) {
35076 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
35077 goto exit;
35078 }
35079 iop_a_src += 6;
35080 *iop_a_dst++ = wuffs_base__make_token(
35081 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35082 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35083 (((uint64_t)(6)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35084 goto label__string_loop_outer__continue;
35085 }
35086 } else if ((v_c == 85) && self->private_impl.f_quirks[2]) {
35087 if (((uint64_t)(io2_a_src - iop_a_src)) < 10) {
35088 if (a_src && a_src->meta.closed) {
35089 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
35090 goto exit;
35091 }
35092 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35093 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
Nigel Taoe360a532021-04-05 22:47:03 +100035094 goto label__string_loop_outer__continue;
35095 }
35096 v_uni8_string = wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 2);
35097 v_uni8_value = 0;
35098 v_uni8_ok = 128;
35099 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 0))];
35100 v_uni8_ok &= v_c;
35101 v_uni8_value |= (((uint32_t)((v_c & 15))) << 28);
35102 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 8))];
35103 v_uni8_ok &= v_c;
35104 v_uni8_value |= (((uint32_t)((v_c & 15))) << 24);
35105 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 16))];
35106 v_uni8_ok &= v_c;
35107 v_uni8_value |= (((uint32_t)((v_c & 15))) << 20);
35108 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 24))];
35109 v_uni8_ok &= v_c;
35110 v_uni8_value |= (((uint32_t)((v_c & 15))) << 16);
35111 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 32))];
35112 v_uni8_ok &= v_c;
35113 v_uni8_value |= (((uint32_t)((v_c & 15))) << 12);
35114 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 40))];
35115 v_uni8_ok &= v_c;
35116 v_uni8_value |= (((uint32_t)((v_c & 15))) << 8);
35117 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 48))];
35118 v_uni8_ok &= v_c;
35119 v_uni8_value |= (((uint32_t)((v_c & 15))) << 4);
35120 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_uni8_string >> 56))];
35121 v_uni8_ok &= v_c;
35122 v_uni8_value |= (((uint32_t)((v_c & 15))) << 0);
35123 if (v_uni8_ok == 0) {
35124 } else if ((v_uni8_value < 55296) || ((57343 < v_uni8_value) && (v_uni8_value <= 1114111))) {
35125 iop_a_src += 10;
35126 *iop_a_dst++ = wuffs_base__make_token(
35127 (((uint64_t)((6291456 | (v_uni8_value & 2097151)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35128 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35129 (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35130 goto label__string_loop_outer__continue;
35131 } else if (self->private_impl.f_quirks[20]) {
35132 iop_a_src += 10;
35133 *iop_a_dst++ = wuffs_base__make_token(
35134 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35135 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35136 (((uint64_t)(10)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35137 goto label__string_loop_outer__continue;
35138 }
35139 } else if ((v_c == 120) && self->private_impl.f_quirks[9]) {
35140 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
35141 if (a_src && a_src->meta.closed) {
35142 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
35143 goto exit;
35144 }
35145 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35146 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
Nigel Taoe360a532021-04-05 22:47:03 +100035147 goto label__string_loop_outer__continue;
35148 }
35149 v_backslash_x_string = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
35150 v_backslash_x_ok = 128;
35151 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 16))];
35152 v_backslash_x_ok &= v_c;
35153 v_backslash_x_value = ((uint8_t)(((v_c & 15) << 4)));
35154 v_c = WUFFS_JSON__LUT_HEXADECIMAL_DIGITS[(255 & (v_backslash_x_string >> 24))];
35155 v_backslash_x_ok &= v_c;
35156 v_backslash_x_value = ((uint8_t)((v_backslash_x_value | (v_c & 15))));
35157 if ((v_backslash_x_ok == 0) || ((v_backslash_x_string & 65535) != 30812)) {
35158 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
35159 goto exit;
35160 }
35161 iop_a_src += 4;
35162 *iop_a_dst++ = wuffs_base__make_token(
35163 (((uint64_t)((6291456 | ((uint32_t)(v_backslash_x_value))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35164 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35165 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35166 goto label__string_loop_outer__continue;
35167 }
35168 status = wuffs_base__make_status(wuffs_json__error__bad_backslash_escape);
35169 goto exit;
35170 } else if (v_char == 3) {
35171 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
35172 if (v_string_length > 0) {
35173 *iop_a_dst++ = wuffs_base__make_token(
35174 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35175 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35176 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35177 v_string_length = 0;
35178 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35179 goto label__string_loop_outer__continue;
35180 }
35181 }
35182 if (a_src && a_src->meta.closed) {
35183 if (self->private_impl.f_quirks[20]) {
35184 *iop_a_dst++ = wuffs_base__make_token(
35185 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35186 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35187 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35188 iop_a_src += 1;
35189 goto label__string_loop_outer__continue;
35190 }
35191 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
35192 goto exit;
35193 }
35194 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35195 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
Nigel Taoe360a532021-04-05 22:47:03 +100035196 goto label__string_loop_outer__continue;
35197 }
35198 v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
35199 if ((v_multi_byte_utf8 & 49152) == 32768) {
35200 v_multi_byte_utf8 = ((1984 & ((uint32_t)(v_multi_byte_utf8 << 6))) | (63 & (v_multi_byte_utf8 >> 8)));
35201 iop_a_src += 2;
35202 if (v_string_length >= 65528) {
35203 *iop_a_dst++ = wuffs_base__make_token(
35204 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35205 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35206 (((uint64_t)((v_string_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35207 v_string_length = 0;
35208 goto label__string_loop_outer__continue;
35209 }
35210 v_string_length += 2;
35211 goto label__string_loop_inner__continue;
35212 }
35213 } else if (v_char == 4) {
35214 if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
35215 if (v_string_length > 0) {
35216 *iop_a_dst++ = wuffs_base__make_token(
35217 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35218 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35219 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35220 v_string_length = 0;
35221 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35222 goto label__string_loop_outer__continue;
35223 }
35224 }
35225 if (a_src && a_src->meta.closed) {
35226 if (self->private_impl.f_quirks[20]) {
35227 *iop_a_dst++ = wuffs_base__make_token(
35228 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35229 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35230 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35231 iop_a_src += 1;
35232 goto label__string_loop_outer__continue;
35233 }
35234 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
35235 goto exit;
35236 }
35237 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35238 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(12);
Nigel Taoe360a532021-04-05 22:47:03 +100035239 goto label__string_loop_outer__continue;
35240 }
35241 v_multi_byte_utf8 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
35242 if ((v_multi_byte_utf8 & 12632064) == 8421376) {
35243 v_multi_byte_utf8 = ((61440 & ((uint32_t)(v_multi_byte_utf8 << 12))) | (4032 & (v_multi_byte_utf8 >> 2)) | (63 & (v_multi_byte_utf8 >> 16)));
35244 if ((2047 < v_multi_byte_utf8) && ((v_multi_byte_utf8 < 55296) || (57343 < v_multi_byte_utf8))) {
35245 iop_a_src += 3;
35246 if (v_string_length >= 65528) {
35247 *iop_a_dst++ = wuffs_base__make_token(
35248 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35249 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35250 (((uint64_t)((v_string_length + 3))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35251 v_string_length = 0;
35252 goto label__string_loop_outer__continue;
35253 }
35254 v_string_length += 3;
35255 goto label__string_loop_inner__continue;
35256 }
35257 }
35258 } else if (v_char == 5) {
35259 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
35260 if (v_string_length > 0) {
35261 *iop_a_dst++ = wuffs_base__make_token(
35262 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35263 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35264 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35265 v_string_length = 0;
35266 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35267 goto label__string_loop_outer__continue;
35268 }
35269 }
35270 if (a_src && a_src->meta.closed) {
35271 if (self->private_impl.f_quirks[20]) {
35272 *iop_a_dst++ = wuffs_base__make_token(
35273 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35274 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35275 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35276 iop_a_src += 1;
35277 goto label__string_loop_outer__continue;
35278 }
35279 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
35280 goto exit;
35281 }
35282 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35283 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(13);
Nigel Taoe360a532021-04-05 22:47:03 +100035284 goto label__string_loop_outer__continue;
35285 }
35286 v_multi_byte_utf8 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
35287 if ((v_multi_byte_utf8 & 3233857536) == 2155905024) {
35288 v_multi_byte_utf8 = ((1835008 & ((uint32_t)(v_multi_byte_utf8 << 18))) |
35289 (258048 & ((uint32_t)(v_multi_byte_utf8 << 4))) |
35290 (4032 & (v_multi_byte_utf8 >> 10)) |
35291 (63 & (v_multi_byte_utf8 >> 24)));
35292 if ((65535 < v_multi_byte_utf8) && (v_multi_byte_utf8 <= 1114111)) {
35293 iop_a_src += 4;
35294 if (v_string_length >= 65528) {
35295 *iop_a_dst++ = wuffs_base__make_token(
35296 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35297 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35298 (((uint64_t)((v_string_length + 4))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35299 v_string_length = 0;
35300 goto label__string_loop_outer__continue;
35301 }
35302 v_string_length += 4;
35303 goto label__string_loop_inner__continue;
35304 }
35305 }
35306 }
35307 if (v_string_length > 0) {
35308 *iop_a_dst++ = wuffs_base__make_token(
35309 (((uint64_t)(4194819)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35310 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35311 (((uint64_t)(v_string_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35312 v_string_length = 0;
35313 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35314 goto label__string_loop_outer__continue;
35315 }
35316 }
35317 if ((v_char & 128) != 0) {
35318 if (self->private_impl.f_quirks[0]) {
35319 *iop_a_dst++ = wuffs_base__make_token(
35320 (((uint64_t)((6291456 | ((uint32_t)((v_char & 127)))))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35321 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35322 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35323 iop_a_src += 1;
35324 goto label__string_loop_outer__continue;
35325 }
35326 if (v_char == 138) {
35327 status = wuffs_base__make_status(wuffs_json__error__bad_new_line_in_a_string);
35328 goto exit;
35329 }
35330 status = wuffs_base__make_status(wuffs_json__error__bad_c0_control_code);
35331 goto exit;
35332 }
35333 if (self->private_impl.f_quirks[20]) {
35334 *iop_a_dst++ = wuffs_base__make_token(
35335 (((uint64_t)(6356989)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35336 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
35337 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35338 iop_a_src += 1;
35339 goto label__string_loop_outer__continue;
35340 }
35341 status = wuffs_base__make_status(wuffs_json__error__bad_utf_8);
35342 goto exit;
35343 }
35344 }
35345 label__string_loop_outer__break:;
35346 label__1__continue:;
35347 while (true) {
35348 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35349 if (a_src && a_src->meta.closed) {
35350 status = wuffs_base__make_status(wuffs_json__error__bad_input);
35351 goto exit;
35352 }
35353 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35354 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(14);
35355 goto label__1__continue;
35356 }
35357 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35358 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
35359 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(15);
35360 goto label__1__continue;
35361 }
35362 iop_a_src += 1;
35363 *iop_a_dst++ = wuffs_base__make_token(
35364 (((uint64_t)(4194579)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35365 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35366 goto label__1__break;
35367 }
35368 label__1__break:;
35369 if (0 == (v_expect & (((uint32_t)(1)) << 4))) {
35370 v_expect = 4104;
35371 goto label__outer__continue;
35372 }
35373 goto label__goto_parsed_a_leaf_value__break;
35374 } else if (v_class == 2) {
35375 iop_a_src += 1;
35376 *iop_a_dst++ = wuffs_base__make_token(
35377 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35378 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35379 if (0 == (v_expect & (((uint32_t)(1)) << 8))) {
35380 if (self->private_impl.f_quirks[13]) {
35381 v_expect = 4162;
35382 } else {
35383 v_expect = 4098;
35384 }
35385 } else {
35386 if (self->private_impl.f_quirks[13]) {
35387 v_expect = 8114;
35388 } else {
35389 v_expect = 7858;
35390 }
35391 }
35392 goto label__outer__continue;
35393 } else if (v_class == 3) {
35394 iop_a_src += 1;
35395 *iop_a_dst++ = wuffs_base__make_token(
35396 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35397 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35398 v_expect = 7858;
35399 goto label__outer__continue;
35400 } else if (v_class == 4) {
35401 while (true) {
35402 if (a_src) {
35403 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35404 }
35405 v_number_length = wuffs_json__decoder__decode_number(self, a_src);
35406 if (a_src) {
35407 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35408 }
35409 v_number_status = (v_number_length >> 8);
35410 v_vminor = 10486787;
35411 if ((v_number_length & 128) != 0) {
35412 v_vminor = 10486785;
35413 }
35414 v_number_length = (v_number_length & 127);
35415 if (v_number_status == 0) {
35416 *iop_a_dst++ = wuffs_base__make_token(
35417 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35418 (((uint64_t)(v_number_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35419 goto label__2__break;
35420 }
35421 while (v_number_length > 0) {
35422 v_number_length -= 1;
35423 if (iop_a_src > io1_a_src) {
35424 iop_a_src--;
35425 } else {
35426 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
35427 goto exit;
35428 }
35429 }
35430 if (v_number_status == 1) {
35431 if (self->private_impl.f_quirks[14]) {
35432 if (a_dst) {
35433 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35434 }
35435 if (a_src) {
35436 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35437 }
35438 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
35439 status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
35440 if (a_dst) {
35441 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
35442 }
35443 if (a_src) {
35444 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35445 }
35446 if (status.repr) {
35447 goto suspend;
35448 }
35449 goto label__2__break;
35450 }
35451 status = wuffs_base__make_status(wuffs_json__error__bad_input);
35452 goto exit;
35453 } else if (v_number_status == 2) {
35454 status = wuffs_base__make_status(wuffs_json__error__unsupported_number_length);
35455 goto exit;
35456 } else {
35457 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35458 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(17);
35459 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35460 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
35461 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(18);
35462 }
35463 }
35464 }
35465 label__2__break:;
35466 goto label__goto_parsed_a_leaf_value__break;
35467 } else if (v_class == 5) {
35468 v_vminor = 2113553;
35469 if (v_depth == 0) {
35470 } else if (0 != (v_expect_after_value & (((uint32_t)(1)) << 6))) {
35471 v_vminor = 2113601;
35472 } else {
35473 v_vminor = 2113569;
35474 }
35475 if (v_depth >= 1024) {
35476 status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth);
35477 goto exit;
35478 }
35479 v_stack_byte = (v_depth / 32);
35480 v_stack_bit = (v_depth & 31);
35481 self->private_data.f_stack[v_stack_byte] |= (((uint32_t)(1)) << v_stack_bit);
35482 v_depth += 1;
35483 iop_a_src += 1;
35484 *iop_a_dst++ = wuffs_base__make_token(
35485 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35486 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35487 v_expect = 4162;
35488 v_expect_after_value = 4164;
35489 goto label__outer__continue;
35490 } else if (v_class == 6) {
35491 iop_a_src += 1;
35492 if (v_depth <= 1) {
35493 *iop_a_dst++ = wuffs_base__make_token(
35494 (((uint64_t)(2101314)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35495 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35496 goto label__outer__break;
35497 }
35498 v_depth -= 1;
35499 v_stack_byte = ((v_depth - 1) / 32);
35500 v_stack_bit = ((v_depth - 1) & 31);
35501 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
35502 *iop_a_dst++ = wuffs_base__make_token(
35503 (((uint64_t)(2105410)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35504 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35505 v_expect = 4356;
35506 v_expect_after_value = 4356;
35507 } else {
35508 *iop_a_dst++ = wuffs_base__make_token(
35509 (((uint64_t)(2113602)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35510 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35511 v_expect = 4164;
35512 v_expect_after_value = 4164;
35513 }
35514 goto label__outer__continue;
35515 } else if (v_class == 7) {
35516 v_vminor = 2105361;
35517 if (v_depth == 0) {
35518 } else if (0 != (v_expect_after_value & (((uint32_t)(1)) << 6))) {
35519 v_vminor = 2105409;
35520 } else {
35521 v_vminor = 2105377;
35522 }
35523 if (v_depth >= 1024) {
35524 status = wuffs_base__make_status(wuffs_json__error__unsupported_recursion_depth);
35525 goto exit;
35526 }
35527 v_stack_byte = (v_depth / 32);
35528 v_stack_bit = (v_depth & 31);
35529 self->private_data.f_stack[v_stack_byte] &= (4294967295 ^ (((uint32_t)(1)) << v_stack_bit));
35530 v_depth += 1;
35531 iop_a_src += 1;
35532 *iop_a_dst++ = wuffs_base__make_token(
35533 (((uint64_t)(v_vminor)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35534 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35535 v_expect = 8114;
35536 v_expect_after_value = 4356;
35537 goto label__outer__continue;
35538 } else if (v_class == 8) {
35539 iop_a_src += 1;
35540 if (v_depth <= 1) {
35541 *iop_a_dst++ = wuffs_base__make_token(
35542 (((uint64_t)(2101282)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35543 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35544 goto label__outer__break;
35545 }
35546 v_depth -= 1;
35547 v_stack_byte = ((v_depth - 1) / 32);
35548 v_stack_bit = ((v_depth - 1) & 31);
35549 if (0 == (self->private_data.f_stack[v_stack_byte] & (((uint32_t)(1)) << v_stack_bit))) {
35550 *iop_a_dst++ = wuffs_base__make_token(
35551 (((uint64_t)(2105378)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35552 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35553 v_expect = 4356;
35554 v_expect_after_value = 4356;
35555 } else {
35556 *iop_a_dst++ = wuffs_base__make_token(
35557 (((uint64_t)(2113570)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35558 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35559 v_expect = 4164;
35560 v_expect_after_value = 4164;
35561 }
35562 goto label__outer__continue;
35563 } else if (v_class == 9) {
35564 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,111546413966853);
35565 if (v_match == 0) {
35566 *iop_a_dst++ = wuffs_base__make_token(
35567 (((uint64_t)(8388612)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35568 (((uint64_t)(5)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35569 if (((uint64_t)(io2_a_src - iop_a_src)) < 5) {
35570 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
35571 goto exit;
35572 }
35573 iop_a_src += 5;
35574 goto label__goto_parsed_a_leaf_value__break;
35575 } else if (v_match == 1) {
35576 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35577 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(19);
35578 goto label__outer__continue;
35579 }
35580 } else if (v_class == 10) {
35581 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,435762131972);
35582 if (v_match == 0) {
35583 *iop_a_dst++ = wuffs_base__make_token(
35584 (((uint64_t)(8388616)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35585 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35586 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
35587 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
35588 goto exit;
35589 }
35590 iop_a_src += 4;
35591 goto label__goto_parsed_a_leaf_value__break;
35592 } else if (v_match == 1) {
35593 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35594 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(20);
35595 goto label__outer__continue;
35596 }
35597 } else if (v_class == 11) {
35598 v_match = wuffs_base__io_reader__match7(iop_a_src, io2_a_src, a_src,465676103172);
35599 if (v_match == 0) {
35600 *iop_a_dst++ = wuffs_base__make_token(
35601 (((uint64_t)(8388610)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35602 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35603 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
35604 status = wuffs_base__make_status(wuffs_json__error__internal_error_inconsistent_i_o);
35605 goto exit;
35606 }
35607 iop_a_src += 4;
35608 goto label__goto_parsed_a_leaf_value__break;
35609 } else if (v_match == 1) {
35610 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35611 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(21);
35612 goto label__outer__continue;
35613 }
35614 if (self->private_impl.f_quirks[14]) {
35615 if (a_dst) {
35616 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35617 }
35618 if (a_src) {
35619 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35620 }
35621 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
35622 status = wuffs_json__decoder__decode_inf_nan(self, a_dst, a_src);
35623 if (a_dst) {
35624 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
35625 }
35626 if (a_src) {
35627 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35628 }
35629 if (status.repr) {
35630 goto suspend;
35631 }
35632 goto label__goto_parsed_a_leaf_value__break;
35633 }
35634 } else if (v_class == 12) {
35635 if (self->private_impl.f_quirks[11] || self->private_impl.f_quirks[12]) {
35636 if (a_dst) {
35637 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35638 }
35639 if (a_src) {
35640 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35641 }
35642 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(23);
35643 status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
35644 if (a_dst) {
35645 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
35646 }
35647 if (a_src) {
35648 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35649 }
35650 if (status.repr) {
35651 goto suspend;
35652 }
35653 if (self->private_impl.f_comment_type > 0) {
35654 goto label__outer__continue;
35655 }
35656 }
35657 }
35658 status = wuffs_base__make_status(wuffs_json__error__bad_input);
35659 goto exit;
35660 }
35661 label__goto_parsed_a_leaf_value__break:;
35662 if (v_depth == 0) {
35663 goto label__outer__break;
35664 }
35665 v_expect = v_expect_after_value;
35666 }
35667 label__outer__break:;
35668 if (self->private_impl.f_quirks[17] || self->private_impl.f_quirks[18]) {
35669 if (a_dst) {
35670 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35671 }
35672 if (a_src) {
35673 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35674 }
35675 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(24);
35676 status = wuffs_json__decoder__decode_trailer(self, a_dst, a_src);
35677 if (a_dst) {
35678 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
35679 }
35680 if (a_src) {
35681 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35682 }
35683 if (status.repr) {
35684 goto suspend;
35685 }
35686 }
35687 self->private_impl.f_end_of_data = true;
35688
Nigel Taoe360a532021-04-05 22:47:03 +100035689 ok:
35690 self->private_impl.p_decode_tokens[0] = 0;
35691 goto exit;
35692 }
35693
35694 goto suspend;
35695 suspend:
35696 self->private_impl.p_decode_tokens[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
35697 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
35698 self->private_data.s_decode_tokens[0].v_depth = v_depth;
35699 self->private_data.s_decode_tokens[0].v_expect = v_expect;
35700 self->private_data.s_decode_tokens[0].v_expect_after_value = v_expect_after_value;
35701
35702 goto exit;
35703 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110035704 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035705 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
35706 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110035707 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035708 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35709 }
35710
35711 if (wuffs_base__status__is_error(&status)) {
35712 self->private_impl.magic = WUFFS_BASE__DISABLED;
35713 }
35714 return status;
35715}
35716
35717// -------- func json.decoder.decode_number
35718
35719static uint32_t
35720wuffs_json__decoder__decode_number(
35721 wuffs_json__decoder* self,
35722 wuffs_base__io_buffer* a_src) {
35723 uint8_t v_c = 0;
35724 uint32_t v_n = 0;
35725 uint32_t v_floating_point = 0;
35726
35727 const uint8_t* iop_a_src = NULL;
35728 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35729 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35730 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110035731 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035732 io0_a_src = a_src->data.ptr;
35733 io1_a_src = io0_a_src + a_src->meta.ri;
35734 iop_a_src = io1_a_src;
35735 io2_a_src = io0_a_src + a_src->meta.wi;
35736 }
35737
35738 while (true) {
35739 v_n = 0;
35740 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35741 if ( ! (a_src && a_src->meta.closed)) {
35742 v_n |= 768;
35743 }
35744 goto label__goto_done__break;
35745 }
35746 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35747 if (v_c != 45) {
35748 } else {
35749 v_n += 1;
35750 iop_a_src += 1;
35751 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35752 if ( ! (a_src && a_src->meta.closed)) {
35753 v_n |= 768;
35754 }
35755 v_n |= 256;
35756 goto label__goto_done__break;
35757 }
35758 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35759 }
35760 if (v_c == 48) {
35761 v_n += 1;
35762 iop_a_src += 1;
35763 } else {
35764 if (a_src) {
35765 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35766 }
35767 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
35768 if (a_src) {
35769 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35770 }
35771 if (v_n > 99) {
35772 goto label__goto_done__break;
35773 }
35774 }
35775 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35776 if ( ! (a_src && a_src->meta.closed)) {
35777 v_n |= 768;
35778 }
35779 goto label__goto_done__break;
35780 }
35781 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35782 if (v_c != 46) {
35783 } else {
35784 if (v_n >= 99) {
35785 v_n |= 512;
35786 goto label__goto_done__break;
35787 }
35788 v_n += 1;
35789 iop_a_src += 1;
35790 v_floating_point = 128;
35791 if (a_src) {
35792 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35793 }
35794 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
35795 if (a_src) {
35796 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35797 }
35798 if (v_n > 99) {
35799 goto label__goto_done__break;
35800 }
35801 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35802 if ( ! (a_src && a_src->meta.closed)) {
35803 v_n |= 768;
35804 }
35805 goto label__goto_done__break;
35806 }
35807 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35808 }
35809 if ((v_c != 69) && (v_c != 101)) {
35810 goto label__goto_done__break;
35811 }
35812 if (v_n >= 99) {
35813 v_n |= 512;
35814 goto label__goto_done__break;
35815 }
35816 v_n += 1;
35817 iop_a_src += 1;
35818 v_floating_point = 128;
35819 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35820 if ( ! (a_src && a_src->meta.closed)) {
35821 v_n |= 768;
35822 }
35823 v_n |= 256;
35824 goto label__goto_done__break;
35825 }
35826 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35827 if ((v_c != 43) && (v_c != 45)) {
35828 } else {
35829 if (v_n >= 99) {
35830 v_n |= 512;
35831 goto label__goto_done__break;
35832 }
35833 v_n += 1;
35834 iop_a_src += 1;
35835 }
35836 if (a_src) {
35837 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35838 }
35839 v_n = wuffs_json__decoder__decode_digits(self, a_src, v_n);
35840 if (a_src) {
35841 iop_a_src = a_src->data.ptr + a_src->meta.ri;
35842 }
35843 goto label__goto_done__break;
35844 }
35845 label__goto_done__break:;
Nigel Taoa0041ac2022-10-20 11:24:24 +110035846 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035847 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35848 }
35849 return (v_n | v_floating_point);
35850}
35851
35852// -------- func json.decoder.decode_digits
35853
35854static uint32_t
35855wuffs_json__decoder__decode_digits(
35856 wuffs_json__decoder* self,
35857 wuffs_base__io_buffer* a_src,
35858 uint32_t a_n) {
35859 uint8_t v_c = 0;
35860 uint32_t v_n = 0;
35861
35862 const uint8_t* iop_a_src = NULL;
35863 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35864 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35865 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110035866 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035867 io0_a_src = a_src->data.ptr;
35868 io1_a_src = io0_a_src + a_src->meta.ri;
35869 iop_a_src = io1_a_src;
35870 io2_a_src = io0_a_src + a_src->meta.wi;
35871 }
35872
35873 v_n = a_n;
35874 while (true) {
35875 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35876 if ( ! (a_src && a_src->meta.closed)) {
35877 v_n |= 768;
35878 }
35879 goto label__0__break;
35880 }
35881 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35882 if (0 == WUFFS_JSON__LUT_DECIMAL_DIGITS[v_c]) {
35883 goto label__0__break;
35884 }
35885 if (v_n >= 99) {
35886 v_n |= 512;
35887 goto label__0__break;
35888 }
35889 v_n += 1;
35890 iop_a_src += 1;
35891 }
35892 label__0__break:;
35893 if (v_n == a_n) {
35894 v_n |= 256;
35895 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110035896 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035897 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
35898 }
35899 return v_n;
35900}
35901
35902// -------- func json.decoder.decode_leading
35903
35904static wuffs_base__status
35905wuffs_json__decoder__decode_leading(
35906 wuffs_json__decoder* self,
35907 wuffs_base__token_buffer* a_dst,
35908 wuffs_base__io_buffer* a_src) {
35909 wuffs_base__status status = wuffs_base__make_status(NULL);
35910
35911 uint8_t v_c = 0;
35912 uint32_t v_u = 0;
35913
35914 wuffs_base__token* iop_a_dst = NULL;
35915 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35916 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35917 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110035918 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035919 io0_a_dst = a_dst->data.ptr;
35920 io1_a_dst = io0_a_dst + a_dst->meta.wi;
35921 iop_a_dst = io1_a_dst;
35922 io2_a_dst = io0_a_dst + a_dst->data.len;
35923 if (a_dst->meta.closed) {
35924 io2_a_dst = iop_a_dst;
35925 }
35926 }
35927 const uint8_t* iop_a_src = NULL;
35928 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35929 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
35930 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110035931 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100035932 io0_a_src = a_src->data.ptr;
35933 io1_a_src = io0_a_src + a_src->meta.ri;
35934 iop_a_src = io1_a_src;
35935 io2_a_src = io0_a_src + a_src->meta.wi;
35936 }
35937
35938 uint32_t coro_susp_point = self->private_impl.p_decode_leading[0];
35939 switch (coro_susp_point) {
35940 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
35941
35942 self->private_impl.f_allow_leading_ars = self->private_impl.f_quirks[15];
35943 self->private_impl.f_allow_leading_ubom = self->private_impl.f_quirks[16];
35944 label__0__continue:;
35945 while (self->private_impl.f_allow_leading_ars || self->private_impl.f_allow_leading_ubom) {
35946 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
35947 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
35948 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
35949 goto label__0__continue;
35950 }
35951 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
35952 if (a_src && a_src->meta.closed) {
35953 goto label__0__break;
35954 }
35955 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35956 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
35957 goto label__0__continue;
35958 }
35959 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
35960 if ((v_c == 30) && self->private_impl.f_allow_leading_ars) {
35961 self->private_impl.f_allow_leading_ars = false;
35962 iop_a_src += 1;
35963 *iop_a_dst++ = wuffs_base__make_token(
35964 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35965 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35966 goto label__0__continue;
35967 } else if ((v_c == 239) && self->private_impl.f_allow_leading_ubom) {
35968 if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
35969 if (a_src && a_src->meta.closed) {
35970 goto label__0__break;
35971 }
35972 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
35973 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
35974 goto label__0__continue;
35975 }
35976 v_u = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
35977 if (v_u == 12565487) {
35978 self->private_impl.f_allow_leading_ubom = false;
35979 iop_a_src += 3;
35980 *iop_a_dst++ = wuffs_base__make_token(
35981 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
35982 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
35983 goto label__0__continue;
35984 }
35985 }
35986 goto label__0__break;
35987 }
35988 label__0__break:;
35989
Nigel Taoe360a532021-04-05 22:47:03 +100035990 ok:
35991 self->private_impl.p_decode_leading[0] = 0;
35992 goto exit;
35993 }
35994
35995 goto suspend;
35996 suspend:
35997 self->private_impl.p_decode_leading[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
35998
35999 goto exit;
36000 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036001 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036002 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
36003 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110036004 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036005 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36006 }
36007
36008 return status;
36009}
36010
36011// -------- func json.decoder.decode_comment
36012
36013static wuffs_base__status
36014wuffs_json__decoder__decode_comment(
36015 wuffs_json__decoder* self,
36016 wuffs_base__token_buffer* a_dst,
36017 wuffs_base__io_buffer* a_src) {
36018 wuffs_base__status status = wuffs_base__make_status(NULL);
36019
36020 uint8_t v_c = 0;
36021 uint16_t v_c2 = 0;
36022 uint32_t v_length = 0;
36023
36024 wuffs_base__token* iop_a_dst = NULL;
36025 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36026 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36027 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036028 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036029 io0_a_dst = a_dst->data.ptr;
36030 io1_a_dst = io0_a_dst + a_dst->meta.wi;
36031 iop_a_dst = io1_a_dst;
36032 io2_a_dst = io0_a_dst + a_dst->data.len;
36033 if (a_dst->meta.closed) {
36034 io2_a_dst = iop_a_dst;
36035 }
36036 }
36037 const uint8_t* iop_a_src = NULL;
36038 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36039 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36040 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036041 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036042 io0_a_src = a_src->data.ptr;
36043 io1_a_src = io0_a_src + a_src->meta.ri;
36044 iop_a_src = io1_a_src;
36045 io2_a_src = io0_a_src + a_src->meta.wi;
36046 }
36047
36048 uint32_t coro_susp_point = self->private_impl.p_decode_comment[0];
36049 switch (coro_susp_point) {
36050 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
36051
36052 self->private_impl.f_comment_type = 0;
36053 label__0__continue:;
36054 while ((((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) || (((uint64_t)(io2_a_src - iop_a_src)) <= 1)) {
36055 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36056 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36057 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
36058 goto label__0__continue;
36059 }
36060 if (a_src && a_src->meta.closed) {
36061 status = wuffs_base__make_status(NULL);
36062 goto ok;
36063 }
36064 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36065 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
36066 }
36067 v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
36068 if ((v_c2 == 10799) && self->private_impl.f_quirks[11]) {
36069 iop_a_src += 2;
36070 v_length = 2;
36071 label__comment_block__continue:;
36072 while (true) {
Nigel Tao123a5c62022-06-03 14:17:20 +100036073 if (((uint64_t)(io2_a_src - iop_a_src)) <= 1) {
36074 if (v_length > 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100036075 *iop_a_dst++ = wuffs_base__make_token(
36076 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36077 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
Nigel Tao123a5c62022-06-03 14:17:20 +100036078 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036079 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036080 if (a_src && a_src->meta.closed) {
36081 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36082 goto exit;
36083 }
36084 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36085 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
36086 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36087 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36088 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
36089 }
36090 v_length = 0;
36091 goto label__comment_block__continue;
Nigel Taoe360a532021-04-05 22:47:03 +100036092 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036093 v_c2 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
36094 if (v_c2 == 12074) {
36095 iop_a_src += 2;
36096 *iop_a_dst++ = wuffs_base__make_token(
36097 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36098 (((uint64_t)((v_length + 2))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36099 self->private_impl.f_comment_type = 1;
36100 status = wuffs_base__make_status(NULL);
36101 goto ok;
36102 }
36103 iop_a_src += 1;
36104 if (v_length >= 65533) {
36105 *iop_a_dst++ = wuffs_base__make_token(
36106 (((uint64_t)(2)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36107 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
36108 (((uint64_t)((v_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36109 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36110 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36111 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
36112 }
36113 v_length = 0;
36114 goto label__comment_block__continue;
36115 }
36116 v_length += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100036117 }
36118 } else if ((v_c2 == 12079) && self->private_impl.f_quirks[12]) {
36119 iop_a_src += 2;
36120 v_length = 2;
36121 label__comment_line__continue:;
36122 while (true) {
Nigel Tao123a5c62022-06-03 14:17:20 +100036123 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
36124 if (a_src && a_src->meta.closed) {
Nigel Taoe360a532021-04-05 22:47:03 +100036125 *iop_a_dst++ = wuffs_base__make_token(
36126 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
Nigel Tao600cd962021-07-20 14:22:02 +100036127 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036128 self->private_impl.f_comment_type = 2;
36129 status = wuffs_base__make_status(NULL);
36130 goto ok;
Nigel Tao123a5c62022-06-03 14:17:20 +100036131 } else if (v_length > 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100036132 *iop_a_dst++ = wuffs_base__make_token(
36133 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36134 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
Nigel Tao123a5c62022-06-03 14:17:20 +100036135 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036136 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036137 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36138 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
36139 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36140 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36141 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
36142 }
36143 v_length = 0;
36144 goto label__comment_line__continue;
Nigel Taoe360a532021-04-05 22:47:03 +100036145 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036146 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
36147 if (v_c == 10) {
36148 *iop_a_dst++ = wuffs_base__make_token(
36149 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36150 (((uint64_t)(v_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36151 self->private_impl.f_comment_type = 2;
36152 status = wuffs_base__make_status(NULL);
36153 goto ok;
36154 }
36155 iop_a_src += 1;
36156 if (v_length >= 65533) {
36157 *iop_a_dst++ = wuffs_base__make_token(
36158 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36159 (((uint64_t)(1)) << WUFFS_BASE__TOKEN__CONTINUED__SHIFT) |
36160 (((uint64_t)((v_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36161 while (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36162 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36163 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
36164 }
36165 v_length = 0;
36166 goto label__comment_line__continue;
36167 }
36168 v_length += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100036169 }
36170 }
36171
Nigel Taoe360a532021-04-05 22:47:03 +100036172 ok:
36173 self->private_impl.p_decode_comment[0] = 0;
36174 goto exit;
36175 }
36176
36177 goto suspend;
36178 suspend:
36179 self->private_impl.p_decode_comment[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
36180
36181 goto exit;
36182 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036183 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036184 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
36185 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110036186 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036187 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36188 }
36189
36190 return status;
36191}
36192
36193// -------- func json.decoder.decode_inf_nan
36194
36195static wuffs_base__status
36196wuffs_json__decoder__decode_inf_nan(
36197 wuffs_json__decoder* self,
36198 wuffs_base__token_buffer* a_dst,
36199 wuffs_base__io_buffer* a_src) {
36200 wuffs_base__status status = wuffs_base__make_status(NULL);
36201
36202 uint32_t v_c4 = 0;
36203 uint32_t v_neg = 0;
36204
36205 wuffs_base__token* iop_a_dst = NULL;
36206 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36207 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36208 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036209 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036210 io0_a_dst = a_dst->data.ptr;
36211 io1_a_dst = io0_a_dst + a_dst->meta.wi;
36212 iop_a_dst = io1_a_dst;
36213 io2_a_dst = io0_a_dst + a_dst->data.len;
36214 if (a_dst->meta.closed) {
36215 io2_a_dst = iop_a_dst;
36216 }
36217 }
36218 const uint8_t* iop_a_src = NULL;
36219 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36220 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36221 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036222 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036223 io0_a_src = a_src->data.ptr;
36224 io1_a_src = io0_a_src + a_src->meta.ri;
36225 iop_a_src = io1_a_src;
36226 io2_a_src = io0_a_src + a_src->meta.wi;
36227 }
36228
36229 uint32_t coro_susp_point = self->private_impl.p_decode_inf_nan[0];
Nigel Taoe360a532021-04-05 22:47:03 +100036230 switch (coro_susp_point) {
36231 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
36232
36233 label__0__continue:;
36234 while (true) {
36235 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36236 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36237 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
36238 goto label__0__continue;
36239 }
36240 if (((uint64_t)(io2_a_src - iop_a_src)) <= 2) {
36241 if (a_src && a_src->meta.closed) {
36242 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36243 goto exit;
36244 }
36245 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36246 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
36247 goto label__0__continue;
36248 }
36249 v_c4 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
36250 if ((v_c4 | 2105376) == 6712937) {
36251 if (((uint64_t)(io2_a_src - iop_a_src)) > 7) {
36252 if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) | 2314885530818453536) == 8751735898823356009) {
36253 *iop_a_dst++ = wuffs_base__make_token(
36254 (((uint64_t)(10485792)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36255 (((uint64_t)(8)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36256 iop_a_src += 8;
36257 status = wuffs_base__make_status(NULL);
36258 goto ok;
36259 }
36260 } else if ( ! (a_src && a_src->meta.closed)) {
36261 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36262 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
36263 goto label__0__continue;
36264 }
36265 *iop_a_dst++ = wuffs_base__make_token(
36266 (((uint64_t)(10485792)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36267 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36268 iop_a_src += 3;
36269 status = wuffs_base__make_status(NULL);
36270 goto ok;
36271 } else if ((v_c4 | 2105376) == 7233902) {
36272 *iop_a_dst++ = wuffs_base__make_token(
36273 (((uint64_t)(10485888)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36274 (((uint64_t)(3)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36275 iop_a_src += 3;
36276 status = wuffs_base__make_status(NULL);
36277 goto ok;
36278 } else if ((v_c4 & 255) == 43) {
36279 v_neg = 0;
36280 } else if ((v_c4 & 255) == 45) {
36281 v_neg = 1;
36282 } else {
36283 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36284 goto exit;
36285 }
36286 if (((uint64_t)(io2_a_src - iop_a_src)) <= 3) {
36287 if (a_src && a_src->meta.closed) {
36288 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36289 goto exit;
36290 }
36291 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36292 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
36293 goto label__0__continue;
36294 }
36295 v_c4 = (wuffs_base__peek_u32le__no_bounds_check(iop_a_src) >> 8);
36296 if ((v_c4 | 2105376) == 6712937) {
36297 if (((uint64_t)(io2_a_src - iop_a_src)) > 8) {
36298 if ((wuffs_base__peek_u64le__no_bounds_check(iop_a_src + 1) | 2314885530818453536) == 8751735898823356009) {
36299 *iop_a_dst++ = wuffs_base__make_token(
36300 (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36301 (((uint64_t)(9)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36302 iop_a_src += 9;
36303 status = wuffs_base__make_status(NULL);
36304 goto ok;
36305 }
36306 } else if ( ! (a_src && a_src->meta.closed)) {
36307 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36308 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
36309 goto label__0__continue;
36310 }
36311 *iop_a_dst++ = wuffs_base__make_token(
36312 (((uint64_t)((10485760 | (((uint32_t)(32)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36313 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36314 iop_a_src += 4;
36315 status = wuffs_base__make_status(NULL);
36316 goto ok;
36317 } else if ((v_c4 | 2105376) == 7233902) {
36318 *iop_a_dst++ = wuffs_base__make_token(
36319 (((uint64_t)((10485760 | (((uint32_t)(128)) >> v_neg)))) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36320 (((uint64_t)(4)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
36321 iop_a_src += 4;
36322 status = wuffs_base__make_status(NULL);
36323 goto ok;
36324 }
36325 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36326 goto exit;
36327 }
36328
Nigel Taoe360a532021-04-05 22:47:03 +100036329 ok:
36330 self->private_impl.p_decode_inf_nan[0] = 0;
36331 goto exit;
36332 }
36333
36334 goto suspend;
36335 suspend:
36336 self->private_impl.p_decode_inf_nan[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100036337
36338 goto exit;
36339 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036340 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036341 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
36342 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110036343 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036344 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36345 }
36346
36347 return status;
36348}
36349
36350// -------- func json.decoder.decode_trailer
36351
36352static wuffs_base__status
36353wuffs_json__decoder__decode_trailer(
36354 wuffs_json__decoder* self,
36355 wuffs_base__token_buffer* a_dst,
36356 wuffs_base__io_buffer* a_src) {
36357 wuffs_base__status status = wuffs_base__make_status(NULL);
36358
36359 uint8_t v_c = 0;
36360 uint32_t v_whitespace_length = 0;
36361
36362 wuffs_base__token* iop_a_dst = NULL;
36363 wuffs_base__token* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36364 wuffs_base__token* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36365 wuffs_base__token* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036366 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036367 io0_a_dst = a_dst->data.ptr;
36368 io1_a_dst = io0_a_dst + a_dst->meta.wi;
36369 iop_a_dst = io1_a_dst;
36370 io2_a_dst = io0_a_dst + a_dst->data.len;
36371 if (a_dst->meta.closed) {
36372 io2_a_dst = iop_a_dst;
36373 }
36374 }
36375 const uint8_t* iop_a_src = NULL;
36376 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36377 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36378 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036379 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036380 io0_a_src = a_src->data.ptr;
36381 io1_a_src = io0_a_src + a_src->meta.ri;
36382 iop_a_src = io1_a_src;
36383 io2_a_src = io0_a_src + a_src->meta.wi;
36384 }
36385
36386 uint32_t coro_susp_point = self->private_impl.p_decode_trailer[0];
36387 switch (coro_susp_point) {
36388 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
36389
36390 if (self->private_impl.f_quirks[18]) {
36391 self->private_impl.f_trailer_stop = 10;
36392 } else {
36393 self->private_impl.f_trailer_stop = 0;
36394 }
36395 label__outer__continue:;
36396 while (true) {
36397 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
36398 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
36399 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
Nigel Taoe360a532021-04-05 22:47:03 +100036400 goto label__outer__continue;
36401 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036402 v_whitespace_length = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100036403 while (true) {
36404 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
36405 if (v_whitespace_length > 0) {
36406 *iop_a_dst++ = wuffs_base__make_token(
36407 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36408 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036409 }
36410 if (a_src && a_src->meta.closed) {
36411 goto label__outer__break;
36412 }
36413 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36414 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
Nigel Taoe360a532021-04-05 22:47:03 +100036415 goto label__outer__continue;
36416 }
36417 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
36418 if (WUFFS_JSON__LUT_CLASSES[v_c] != 0) {
36419 if (v_whitespace_length > 0) {
36420 *iop_a_dst++ = wuffs_base__make_token(
36421 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36422 (((uint64_t)(v_whitespace_length)) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036423 }
36424 if (self->private_impl.f_trailer_stop > 0) {
36425 status = wuffs_base__make_status(wuffs_json__error__bad_input);
36426 goto exit;
36427 }
36428 if (a_dst) {
36429 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
36430 }
36431 if (a_src) {
36432 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36433 }
36434 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
36435 status = wuffs_json__decoder__decode_comment(self, a_dst, a_src);
36436 if (a_dst) {
36437 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
36438 }
36439 if (a_src) {
36440 iop_a_src = a_src->data.ptr + a_src->meta.ri;
36441 }
36442 if (status.repr) {
36443 goto suspend;
36444 }
Nigel Taoe360a532021-04-05 22:47:03 +100036445 if (self->private_impl.f_comment_type > 0) {
36446 goto label__outer__continue;
36447 }
36448 status = wuffs_base__make_status(NULL);
36449 goto ok;
36450 }
36451 iop_a_src += 1;
36452 if ((v_whitespace_length >= 65534) || (v_c == self->private_impl.f_trailer_stop)) {
36453 *iop_a_dst++ = wuffs_base__make_token(
36454 (((uint64_t)(0)) << WUFFS_BASE__TOKEN__VALUE_MINOR__SHIFT) |
36455 (((uint64_t)((v_whitespace_length + 1))) << WUFFS_BASE__TOKEN__LENGTH__SHIFT));
Nigel Taoe360a532021-04-05 22:47:03 +100036456 if (v_c == self->private_impl.f_trailer_stop) {
36457 status = wuffs_base__make_status(NULL);
36458 goto ok;
36459 }
36460 goto label__outer__continue;
36461 }
36462 v_whitespace_length += 1;
36463 }
36464 }
36465 label__outer__break:;
36466
Nigel Taoe360a532021-04-05 22:47:03 +100036467 ok:
36468 self->private_impl.p_decode_trailer[0] = 0;
36469 goto exit;
36470 }
36471
36472 goto suspend;
36473 suspend:
36474 self->private_impl.p_decode_trailer[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
36475
36476 goto exit;
36477 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036478 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036479 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
36480 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110036481 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036482 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36483 }
36484
36485 return status;
36486}
36487
36488#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__JSON)
36489
36490#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
36491
36492// ---------------- Status Codes Implementations
36493
36494const char wuffs_nie__error__bad_header[] = "#nie: bad header";
36495const char wuffs_nie__error__unsupported_nie_file[] = "#nie: unsupported NIE file";
36496const char wuffs_nie__note__internal_note_short_read[] = "@nie: internal note: short read";
36497
36498// ---------------- Private Consts
36499
36500// ---------------- Private Initializer Prototypes
36501
36502// ---------------- Private Function Prototypes
36503
36504static wuffs_base__status
36505wuffs_nie__decoder__swizzle(
36506 wuffs_nie__decoder* self,
36507 wuffs_base__pixel_buffer* a_dst,
36508 wuffs_base__io_buffer* a_src);
36509
36510// ---------------- VTables
36511
36512const wuffs_base__image_decoder__func_ptrs
36513wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder = {
36514 (wuffs_base__status(*)(void*,
36515 wuffs_base__pixel_buffer*,
36516 wuffs_base__io_buffer*,
36517 wuffs_base__pixel_blend,
36518 wuffs_base__slice_u8,
36519 wuffs_base__decode_frame_options*))(&wuffs_nie__decoder__decode_frame),
36520 (wuffs_base__status(*)(void*,
36521 wuffs_base__frame_config*,
36522 wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_frame_config),
36523 (wuffs_base__status(*)(void*,
36524 wuffs_base__image_config*,
36525 wuffs_base__io_buffer*))(&wuffs_nie__decoder__decode_image_config),
36526 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_nie__decoder__frame_dirty_rect),
36527 (uint32_t(*)(const void*))(&wuffs_nie__decoder__num_animation_loops),
36528 (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frame_configs),
36529 (uint64_t(*)(const void*))(&wuffs_nie__decoder__num_decoded_frames),
36530 (wuffs_base__status(*)(void*,
36531 uint64_t,
36532 uint64_t))(&wuffs_nie__decoder__restart_frame),
36533 (wuffs_base__empty_struct(*)(void*,
36534 uint32_t,
36535 bool))(&wuffs_nie__decoder__set_quirk_enabled),
36536 (wuffs_base__empty_struct(*)(void*,
36537 uint32_t,
36538 bool))(&wuffs_nie__decoder__set_report_metadata),
36539 (wuffs_base__status(*)(void*,
36540 wuffs_base__io_buffer*,
36541 wuffs_base__more_information*,
36542 wuffs_base__io_buffer*))(&wuffs_nie__decoder__tell_me_more),
36543 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_nie__decoder__workbuf_len),
36544};
36545
36546// ---------------- Initializer Implementations
36547
36548wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
36549wuffs_nie__decoder__initialize(
36550 wuffs_nie__decoder* self,
36551 size_t sizeof_star_self,
36552 uint64_t wuffs_version,
36553 uint32_t options){
36554 if (!self) {
36555 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
36556 }
36557 if (sizeof(*self) != sizeof_star_self) {
36558 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
36559 }
36560 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
36561 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
36562 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
36563 }
36564
36565 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
36566 // The whole point of this if-check is to detect an uninitialized *self.
36567 // We disable the warning on GCC. Clang-5.0 does not have this warning.
36568#if !defined(__clang__) && defined(__GNUC__)
36569#pragma GCC diagnostic push
36570#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
36571#endif
36572 if (self->private_impl.magic != 0) {
36573 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
36574 }
36575#if !defined(__clang__) && defined(__GNUC__)
36576#pragma GCC diagnostic pop
36577#endif
36578 } else {
36579 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
36580 memset(self, 0, sizeof(*self));
36581 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
36582 } else {
36583 memset(&(self->private_impl), 0, sizeof(self->private_impl));
36584 }
36585 }
36586
36587 self->private_impl.magic = WUFFS_BASE__MAGIC;
36588 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
36589 wuffs_base__image_decoder__vtable_name;
36590 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
36591 (const void*)(&wuffs_nie__decoder__func_ptrs_for__wuffs_base__image_decoder);
36592 return wuffs_base__make_status(NULL);
36593}
36594
36595wuffs_nie__decoder*
36596wuffs_nie__decoder__alloc() {
36597 wuffs_nie__decoder* x =
36598 (wuffs_nie__decoder*)(calloc(sizeof(wuffs_nie__decoder), 1));
36599 if (!x) {
36600 return NULL;
36601 }
36602 if (wuffs_nie__decoder__initialize(
36603 x, sizeof(wuffs_nie__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
36604 free(x);
36605 return NULL;
36606 }
36607 return x;
36608}
36609
36610size_t
36611sizeof__wuffs_nie__decoder() {
36612 return sizeof(wuffs_nie__decoder);
36613}
36614
36615// ---------------- Function Implementations
36616
36617// -------- func nie.decoder.set_quirk_enabled
36618
36619WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
36620wuffs_nie__decoder__set_quirk_enabled(
36621 wuffs_nie__decoder* self,
36622 uint32_t a_quirk,
36623 bool a_enabled) {
36624 return wuffs_base__make_empty_struct();
36625}
36626
36627// -------- func nie.decoder.decode_image_config
36628
36629WUFFS_BASE__MAYBE_STATIC wuffs_base__status
36630wuffs_nie__decoder__decode_image_config(
36631 wuffs_nie__decoder* self,
36632 wuffs_base__image_config* a_dst,
36633 wuffs_base__io_buffer* a_src) {
36634 if (!self) {
36635 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
36636 }
36637 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
36638 return wuffs_base__make_status(
36639 (self->private_impl.magic == WUFFS_BASE__DISABLED)
36640 ? wuffs_base__error__disabled_by_previous_error
36641 : wuffs_base__error__initialize_not_called);
36642 }
36643 if (!a_src) {
36644 self->private_impl.magic = WUFFS_BASE__DISABLED;
36645 return wuffs_base__make_status(wuffs_base__error__bad_argument);
36646 }
36647 if ((self->private_impl.active_coroutine != 0) &&
36648 (self->private_impl.active_coroutine != 1)) {
36649 self->private_impl.magic = WUFFS_BASE__DISABLED;
36650 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
36651 }
36652 self->private_impl.active_coroutine = 0;
36653 wuffs_base__status status = wuffs_base__make_status(NULL);
36654
36655 uint32_t v_a = 0;
36656
36657 const uint8_t* iop_a_src = NULL;
36658 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36659 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36660 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036661 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036662 io0_a_src = a_src->data.ptr;
36663 io1_a_src = io0_a_src + a_src->meta.ri;
36664 iop_a_src = io1_a_src;
36665 io2_a_src = io0_a_src + a_src->meta.wi;
36666 }
36667
36668 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
36669 switch (coro_susp_point) {
36670 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
36671
36672 if (self->private_impl.f_call_sequence != 0) {
36673 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
36674 goto exit;
36675 }
36676 {
36677 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
36678 uint32_t t_0;
36679 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
36680 t_0 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
36681 iop_a_src += 4;
36682 } else {
36683 self->private_data.s_decode_image_config[0].scratch = 0;
36684 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
36685 while (true) {
36686 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
36687 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36688 goto suspend;
36689 }
36690 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
36691 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
36692 *scratch <<= 8;
36693 *scratch >>= 8;
36694 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
36695 if (num_bits_0 == 24) {
36696 t_0 = ((uint32_t)(*scratch));
36697 break;
36698 }
36699 num_bits_0 += 8;
36700 *scratch |= ((uint64_t)(num_bits_0)) << 56;
36701 }
36702 }
36703 v_a = t_0;
36704 }
36705 if (v_a != 1169146734) {
36706 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
36707 goto exit;
36708 }
36709 {
36710 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
36711 uint32_t t_1;
36712 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
36713 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
36714 iop_a_src += 4;
36715 } else {
36716 self->private_data.s_decode_image_config[0].scratch = 0;
36717 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
36718 while (true) {
36719 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
36720 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36721 goto suspend;
36722 }
36723 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
36724 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
36725 *scratch <<= 8;
36726 *scratch >>= 8;
36727 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
36728 if (num_bits_1 == 24) {
36729 t_1 = ((uint32_t)(*scratch));
36730 break;
36731 }
36732 num_bits_1 += 8;
36733 *scratch |= ((uint64_t)(num_bits_1)) << 56;
36734 }
36735 }
36736 v_a = t_1;
36737 }
36738 if (v_a == 879649535) {
36739 self->private_impl.f_pixfmt = 2164295816;
36740 } else if (v_a == 946758399) {
36741 self->private_impl.f_pixfmt = 2164308923;
36742 } else if (v_a == 879780607) {
36743 status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file);
36744 goto exit;
36745 } else if (v_a == 946889471) {
36746 status = wuffs_base__make_status(wuffs_nie__error__unsupported_nie_file);
36747 goto exit;
36748 } else {
36749 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
36750 goto exit;
36751 }
36752 {
36753 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
36754 uint32_t t_2;
36755 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
36756 t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
36757 iop_a_src += 4;
36758 } else {
36759 self->private_data.s_decode_image_config[0].scratch = 0;
36760 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
36761 while (true) {
36762 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
36763 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36764 goto suspend;
36765 }
36766 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
36767 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
36768 *scratch <<= 8;
36769 *scratch >>= 8;
36770 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
36771 if (num_bits_2 == 24) {
36772 t_2 = ((uint32_t)(*scratch));
36773 break;
36774 }
36775 num_bits_2 += 8;
36776 *scratch |= ((uint64_t)(num_bits_2)) << 56;
36777 }
36778 }
36779 v_a = t_2;
36780 }
36781 if (v_a >= 2147483648) {
36782 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
36783 goto exit;
36784 }
36785 self->private_impl.f_width = v_a;
36786 {
36787 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
36788 uint32_t t_3;
36789 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
36790 t_3 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
36791 iop_a_src += 4;
36792 } else {
36793 self->private_data.s_decode_image_config[0].scratch = 0;
36794 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
36795 while (true) {
36796 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
36797 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
36798 goto suspend;
36799 }
36800 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
36801 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
36802 *scratch <<= 8;
36803 *scratch >>= 8;
36804 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
36805 if (num_bits_3 == 24) {
36806 t_3 = ((uint32_t)(*scratch));
36807 break;
36808 }
36809 num_bits_3 += 8;
36810 *scratch |= ((uint64_t)(num_bits_3)) << 56;
36811 }
36812 }
36813 v_a = t_3;
36814 }
36815 if (v_a >= 2147483648) {
36816 status = wuffs_base__make_status(wuffs_nie__error__bad_header);
36817 goto exit;
36818 }
36819 self->private_impl.f_height = v_a;
36820 if (a_dst != NULL) {
36821 wuffs_base__image_config__set(
36822 a_dst,
36823 self->private_impl.f_pixfmt,
36824 0,
36825 self->private_impl.f_width,
36826 self->private_impl.f_height,
36827 16,
36828 false);
36829 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036830 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100036831
36832 goto ok;
36833 ok:
36834 self->private_impl.p_decode_image_config[0] = 0;
36835 goto exit;
36836 }
36837
36838 goto suspend;
36839 suspend:
36840 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
36841 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
36842
36843 goto exit;
36844 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036845 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036846 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36847 }
36848
36849 if (wuffs_base__status__is_error(&status)) {
36850 self->private_impl.magic = WUFFS_BASE__DISABLED;
36851 }
36852 return status;
36853}
36854
36855// -------- func nie.decoder.decode_frame_config
36856
36857WUFFS_BASE__MAYBE_STATIC wuffs_base__status
36858wuffs_nie__decoder__decode_frame_config(
36859 wuffs_nie__decoder* self,
36860 wuffs_base__frame_config* a_dst,
36861 wuffs_base__io_buffer* a_src) {
36862 if (!self) {
36863 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
36864 }
36865 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
36866 return wuffs_base__make_status(
36867 (self->private_impl.magic == WUFFS_BASE__DISABLED)
36868 ? wuffs_base__error__disabled_by_previous_error
36869 : wuffs_base__error__initialize_not_called);
36870 }
36871 if (!a_src) {
36872 self->private_impl.magic = WUFFS_BASE__DISABLED;
36873 return wuffs_base__make_status(wuffs_base__error__bad_argument);
36874 }
36875 if ((self->private_impl.active_coroutine != 0) &&
36876 (self->private_impl.active_coroutine != 2)) {
36877 self->private_impl.magic = WUFFS_BASE__DISABLED;
36878 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
36879 }
36880 self->private_impl.active_coroutine = 0;
36881 wuffs_base__status status = wuffs_base__make_status(NULL);
36882
36883 const uint8_t* iop_a_src = NULL;
36884 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36885 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
36886 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110036887 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036888 io0_a_src = a_src->data.ptr;
36889 io1_a_src = io0_a_src + a_src->meta.ri;
36890 iop_a_src = io1_a_src;
36891 io2_a_src = io0_a_src + a_src->meta.wi;
36892 }
36893
36894 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
36895 switch (coro_susp_point) {
36896 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
36897
Nigel Tao123a5c62022-06-03 14:17:20 +100036898 if (self->private_impl.f_call_sequence == 32) {
36899 } else if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100036900 if (a_src) {
36901 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36902 }
36903 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
36904 status = wuffs_nie__decoder__decode_image_config(self, NULL, a_src);
36905 if (a_src) {
36906 iop_a_src = a_src->data.ptr + a_src->meta.ri;
36907 }
36908 if (status.repr) {
36909 goto suspend;
36910 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036911 } else if (self->private_impl.f_call_sequence == 40) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100036912 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 +100036913 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
36914 goto exit;
36915 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036916 } else if (self->private_impl.f_call_sequence == 64) {
36917 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100036918 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
36919 goto ok;
36920 } else {
36921 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
36922 goto ok;
36923 }
36924 if (a_dst != NULL) {
36925 wuffs_base__frame_config__set(
36926 a_dst,
36927 wuffs_base__utility__make_rect_ie_u32(
36928 0,
36929 0,
36930 self->private_impl.f_width,
36931 self->private_impl.f_height),
36932 ((wuffs_base__flicks)(0)),
36933 0,
36934 16,
36935 0,
36936 false,
36937 false,
36938 0);
36939 }
Nigel Tao123a5c62022-06-03 14:17:20 +100036940 self->private_impl.f_call_sequence = 64;
Nigel Taoe360a532021-04-05 22:47:03 +100036941
Nigel Taoe360a532021-04-05 22:47:03 +100036942 ok:
36943 self->private_impl.p_decode_frame_config[0] = 0;
36944 goto exit;
36945 }
36946
36947 goto suspend;
36948 suspend:
36949 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
36950 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
36951
36952 goto exit;
36953 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110036954 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100036955 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
36956 }
36957
36958 if (wuffs_base__status__is_error(&status)) {
36959 self->private_impl.magic = WUFFS_BASE__DISABLED;
36960 }
36961 return status;
36962}
36963
36964// -------- func nie.decoder.decode_frame
36965
36966WUFFS_BASE__MAYBE_STATIC wuffs_base__status
36967wuffs_nie__decoder__decode_frame(
36968 wuffs_nie__decoder* self,
36969 wuffs_base__pixel_buffer* a_dst,
36970 wuffs_base__io_buffer* a_src,
36971 wuffs_base__pixel_blend a_blend,
36972 wuffs_base__slice_u8 a_workbuf,
36973 wuffs_base__decode_frame_options* a_opts) {
36974 if (!self) {
36975 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
36976 }
36977 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
36978 return wuffs_base__make_status(
36979 (self->private_impl.magic == WUFFS_BASE__DISABLED)
36980 ? wuffs_base__error__disabled_by_previous_error
36981 : wuffs_base__error__initialize_not_called);
36982 }
36983 if (!a_dst || !a_src) {
36984 self->private_impl.magic = WUFFS_BASE__DISABLED;
36985 return wuffs_base__make_status(wuffs_base__error__bad_argument);
36986 }
36987 if ((self->private_impl.active_coroutine != 0) &&
36988 (self->private_impl.active_coroutine != 3)) {
36989 self->private_impl.magic = WUFFS_BASE__DISABLED;
36990 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
36991 }
36992 self->private_impl.active_coroutine = 0;
36993 wuffs_base__status status = wuffs_base__make_status(NULL);
36994
36995 wuffs_base__status v_status = wuffs_base__make_status(NULL);
36996
36997 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
36998 switch (coro_susp_point) {
36999 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
37000
Nigel Tao123a5c62022-06-03 14:17:20 +100037001 if (self->private_impl.f_call_sequence == 64) {
37002 } else if (self->private_impl.f_call_sequence < 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100037003 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
37004 status = wuffs_nie__decoder__decode_frame_config(self, NULL, a_src);
37005 if (status.repr) {
37006 goto suspend;
37007 }
Nigel Taoe360a532021-04-05 22:47:03 +100037008 } else {
37009 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
37010 goto ok;
37011 }
37012 self->private_impl.f_dst_x = 0;
37013 self->private_impl.f_dst_y = 0;
37014 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
37015 wuffs_base__pixel_buffer__pixel_format(a_dst),
37016 wuffs_base__pixel_buffer__palette(a_dst),
37017 wuffs_base__utility__make_pixel_format(self->private_impl.f_pixfmt),
37018 wuffs_base__utility__empty_slice_u8(),
37019 a_blend);
37020 if ( ! wuffs_base__status__is_ok(&v_status)) {
37021 status = v_status;
37022 if (wuffs_base__status__is_error(&status)) {
37023 goto exit;
37024 } else if (wuffs_base__status__is_suspension(&status)) {
37025 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
37026 goto exit;
37027 }
37028 goto ok;
37029 }
37030 while (true) {
37031 v_status = wuffs_nie__decoder__swizzle(self, a_dst, a_src);
37032 if (wuffs_base__status__is_ok(&v_status)) {
37033 goto label__0__break;
37034 } else if (v_status.repr != wuffs_nie__note__internal_note_short_read) {
37035 status = v_status;
37036 if (wuffs_base__status__is_error(&status)) {
37037 goto exit;
37038 } else if (wuffs_base__status__is_suspension(&status)) {
37039 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
37040 goto exit;
37041 }
37042 goto ok;
37043 }
37044 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37045 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
37046 }
37047 label__0__break:;
Nigel Tao123a5c62022-06-03 14:17:20 +100037048 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100037049
Nigel Taoe360a532021-04-05 22:47:03 +100037050 ok:
37051 self->private_impl.p_decode_frame[0] = 0;
37052 goto exit;
37053 }
37054
37055 goto suspend;
37056 suspend:
37057 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
37058 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
37059
37060 goto exit;
37061 exit:
37062 if (wuffs_base__status__is_error(&status)) {
37063 self->private_impl.magic = WUFFS_BASE__DISABLED;
37064 }
37065 return status;
37066}
37067
37068// -------- func nie.decoder.swizzle
37069
37070static wuffs_base__status
37071wuffs_nie__decoder__swizzle(
37072 wuffs_nie__decoder* self,
37073 wuffs_base__pixel_buffer* a_dst,
37074 wuffs_base__io_buffer* a_src) {
37075 wuffs_base__status status = wuffs_base__make_status(NULL);
37076
37077 wuffs_base__pixel_format v_dst_pixfmt = {0};
37078 uint32_t v_dst_bits_per_pixel = 0;
37079 uint64_t v_dst_bytes_per_pixel = 0;
37080 uint64_t v_dst_bytes_per_row = 0;
37081 wuffs_base__table_u8 v_tab = {0};
37082 wuffs_base__slice_u8 v_dst = {0};
37083 uint64_t v_i = 0;
37084 uint64_t v_n = 0;
37085
37086 const uint8_t* iop_a_src = NULL;
37087 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37088 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37089 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110037090 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037091 io0_a_src = a_src->data.ptr;
37092 io1_a_src = io0_a_src + a_src->meta.ri;
37093 iop_a_src = io1_a_src;
37094 io2_a_src = io0_a_src + a_src->meta.wi;
37095 }
37096
37097 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
37098 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
37099 if ((v_dst_bits_per_pixel & 7) != 0) {
37100 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
37101 goto exit;
37102 }
37103 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
37104 v_dst_bytes_per_row = (((uint64_t)(self->private_impl.f_width)) * v_dst_bytes_per_pixel);
37105 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
37106 label__0__continue:;
37107 while (true) {
37108 if (self->private_impl.f_dst_x == self->private_impl.f_width) {
37109 self->private_impl.f_dst_x = 0;
37110 self->private_impl.f_dst_y += 1;
37111 if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
37112 goto label__0__break;
37113 }
37114 }
Nigel Taobf9dab32021-11-18 19:19:55 +110037115 v_dst = wuffs_base__table_u8__row_u32(v_tab, self->private_impl.f_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100037116 if (v_dst_bytes_per_row < ((uint64_t)(v_dst.len))) {
37117 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row);
37118 }
37119 v_i = (((uint64_t)(self->private_impl.f_dst_x)) * v_dst_bytes_per_pixel);
37120 if (v_i >= ((uint64_t)(v_dst.len))) {
37121 goto label__0__continue;
37122 }
37123 v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
37124 &self->private_impl.f_swizzler,
37125 wuffs_base__slice_u8__subslice_i(v_dst, v_i),
37126 wuffs_base__pixel_buffer__palette(a_dst),
37127 &iop_a_src,
37128 io2_a_src);
37129 if (v_n == 0) {
37130 status = wuffs_base__make_status(wuffs_nie__note__internal_note_short_read);
37131 goto ok;
37132 }
37133 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_dst_x, ((uint32_t)((v_n & 4294967295))));
37134 }
37135 label__0__break:;
37136 status = wuffs_base__make_status(NULL);
37137 goto ok;
37138
Nigel Taoe360a532021-04-05 22:47:03 +100037139 ok:
37140 goto exit;
37141 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110037142 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037143 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37144 }
37145
37146 return status;
37147}
37148
37149// -------- func nie.decoder.frame_dirty_rect
37150
37151WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
37152wuffs_nie__decoder__frame_dirty_rect(
37153 const wuffs_nie__decoder* self) {
37154 if (!self) {
37155 return wuffs_base__utility__empty_rect_ie_u32();
37156 }
37157 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37158 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37159 return wuffs_base__utility__empty_rect_ie_u32();
37160 }
37161
37162 return wuffs_base__utility__make_rect_ie_u32(
37163 0,
37164 0,
37165 self->private_impl.f_width,
37166 self->private_impl.f_height);
37167}
37168
37169// -------- func nie.decoder.num_animation_loops
37170
37171WUFFS_BASE__MAYBE_STATIC uint32_t
37172wuffs_nie__decoder__num_animation_loops(
37173 const wuffs_nie__decoder* self) {
37174 if (!self) {
37175 return 0;
37176 }
37177 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37178 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37179 return 0;
37180 }
37181
37182 return 0;
37183}
37184
37185// -------- func nie.decoder.num_decoded_frame_configs
37186
37187WUFFS_BASE__MAYBE_STATIC uint64_t
37188wuffs_nie__decoder__num_decoded_frame_configs(
37189 const wuffs_nie__decoder* self) {
37190 if (!self) {
37191 return 0;
37192 }
37193 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37194 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37195 return 0;
37196 }
37197
Nigel Tao123a5c62022-06-03 14:17:20 +100037198 if (self->private_impl.f_call_sequence > 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100037199 return 1;
37200 }
37201 return 0;
37202}
37203
37204// -------- func nie.decoder.num_decoded_frames
37205
37206WUFFS_BASE__MAYBE_STATIC uint64_t
37207wuffs_nie__decoder__num_decoded_frames(
37208 const wuffs_nie__decoder* self) {
37209 if (!self) {
37210 return 0;
37211 }
37212 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37213 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37214 return 0;
37215 }
37216
Nigel Tao123a5c62022-06-03 14:17:20 +100037217 if (self->private_impl.f_call_sequence > 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100037218 return 1;
37219 }
37220 return 0;
37221}
37222
37223// -------- func nie.decoder.restart_frame
37224
37225WUFFS_BASE__MAYBE_STATIC wuffs_base__status
37226wuffs_nie__decoder__restart_frame(
37227 wuffs_nie__decoder* self,
37228 uint64_t a_index,
37229 uint64_t a_io_position) {
37230 if (!self) {
37231 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
37232 }
37233 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37234 return wuffs_base__make_status(
37235 (self->private_impl.magic == WUFFS_BASE__DISABLED)
37236 ? wuffs_base__error__disabled_by_previous_error
37237 : wuffs_base__error__initialize_not_called);
37238 }
37239
Nigel Tao123a5c62022-06-03 14:17:20 +100037240 if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100037241 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
37242 }
37243 if ((a_index != 0) || (a_io_position != 16)) {
37244 return wuffs_base__make_status(wuffs_base__error__bad_argument);
37245 }
Nigel Tao123a5c62022-06-03 14:17:20 +100037246 self->private_impl.f_call_sequence = 40;
Nigel Taoe360a532021-04-05 22:47:03 +100037247 return wuffs_base__make_status(NULL);
37248}
37249
37250// -------- func nie.decoder.set_report_metadata
37251
37252WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
37253wuffs_nie__decoder__set_report_metadata(
37254 wuffs_nie__decoder* self,
37255 uint32_t a_fourcc,
37256 bool a_report) {
37257 return wuffs_base__make_empty_struct();
37258}
37259
37260// -------- func nie.decoder.tell_me_more
37261
37262WUFFS_BASE__MAYBE_STATIC wuffs_base__status
37263wuffs_nie__decoder__tell_me_more(
37264 wuffs_nie__decoder* self,
37265 wuffs_base__io_buffer* a_dst,
37266 wuffs_base__more_information* a_minfo,
37267 wuffs_base__io_buffer* a_src) {
37268 if (!self) {
37269 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
37270 }
37271 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37272 return wuffs_base__make_status(
37273 (self->private_impl.magic == WUFFS_BASE__DISABLED)
37274 ? wuffs_base__error__disabled_by_previous_error
37275 : wuffs_base__error__initialize_not_called);
37276 }
37277 if (!a_dst || !a_src) {
37278 self->private_impl.magic = WUFFS_BASE__DISABLED;
37279 return wuffs_base__make_status(wuffs_base__error__bad_argument);
37280 }
37281 if ((self->private_impl.active_coroutine != 0) &&
37282 (self->private_impl.active_coroutine != 4)) {
37283 self->private_impl.magic = WUFFS_BASE__DISABLED;
37284 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
37285 }
37286 self->private_impl.active_coroutine = 0;
37287 wuffs_base__status status = wuffs_base__make_status(NULL);
37288
37289 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
37290 goto exit;
37291
37292 goto ok;
37293 ok:
37294 goto exit;
37295 exit:
37296 if (wuffs_base__status__is_error(&status)) {
37297 self->private_impl.magic = WUFFS_BASE__DISABLED;
37298 }
37299 return status;
37300}
37301
37302// -------- func nie.decoder.workbuf_len
37303
37304WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
37305wuffs_nie__decoder__workbuf_len(
37306 const wuffs_nie__decoder* self) {
37307 if (!self) {
37308 return wuffs_base__utility__empty_range_ii_u64();
37309 }
37310 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37311 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37312 return wuffs_base__utility__empty_range_ii_u64();
37313 }
37314
37315 return wuffs_base__utility__make_range_ii_u64(0, 0);
37316}
37317
37318#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
37319
37320#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB)
37321
37322// ---------------- Status Codes Implementations
37323
37324const char wuffs_zlib__note__dictionary_required[] = "@zlib: dictionary required";
37325const char wuffs_zlib__error__bad_checksum[] = "#zlib: bad checksum";
37326const char wuffs_zlib__error__bad_compression_method[] = "#zlib: bad compression method";
37327const char wuffs_zlib__error__bad_compression_window_size[] = "#zlib: bad compression window size";
37328const char wuffs_zlib__error__bad_parity_check[] = "#zlib: bad parity check";
37329const char wuffs_zlib__error__incorrect_dictionary[] = "#zlib: incorrect dictionary";
37330
37331// ---------------- Private Consts
37332
Nigel Taoebbecaa2022-01-08 14:08:27 +110037333#define WUFFS_ZLIB__QUIRKS_BASE 2113790976
37334
37335#define WUFFS_ZLIB__QUIRKS_COUNT 1
37336
Nigel Taoe360a532021-04-05 22:47:03 +100037337// ---------------- Private Initializer Prototypes
37338
37339// ---------------- Private Function Prototypes
37340
37341// ---------------- VTables
37342
37343const wuffs_base__io_transformer__func_ptrs
37344wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer = {
37345 (wuffs_base__empty_struct(*)(void*,
37346 uint32_t,
37347 bool))(&wuffs_zlib__decoder__set_quirk_enabled),
37348 (wuffs_base__status(*)(void*,
37349 wuffs_base__io_buffer*,
37350 wuffs_base__io_buffer*,
37351 wuffs_base__slice_u8))(&wuffs_zlib__decoder__transform_io),
37352 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_zlib__decoder__workbuf_len),
37353};
37354
37355// ---------------- Initializer Implementations
37356
37357wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
37358wuffs_zlib__decoder__initialize(
37359 wuffs_zlib__decoder* self,
37360 size_t sizeof_star_self,
37361 uint64_t wuffs_version,
37362 uint32_t options){
37363 if (!self) {
37364 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
37365 }
37366 if (sizeof(*self) != sizeof_star_self) {
37367 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
37368 }
37369 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
37370 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
37371 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
37372 }
37373
37374 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
37375 // The whole point of this if-check is to detect an uninitialized *self.
37376 // We disable the warning on GCC. Clang-5.0 does not have this warning.
37377#if !defined(__clang__) && defined(__GNUC__)
37378#pragma GCC diagnostic push
37379#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
37380#endif
37381 if (self->private_impl.magic != 0) {
37382 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
37383 }
37384#if !defined(__clang__) && defined(__GNUC__)
37385#pragma GCC diagnostic pop
37386#endif
37387 } else {
37388 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
37389 memset(self, 0, sizeof(*self));
37390 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
37391 } else {
37392 memset(&(self->private_impl), 0, sizeof(self->private_impl));
37393 }
37394 }
37395
37396 {
37397 wuffs_base__status z = wuffs_adler32__hasher__initialize(
37398 &self->private_data.f_checksum, sizeof(self->private_data.f_checksum), WUFFS_VERSION, options);
37399 if (z.repr) {
37400 return z;
37401 }
37402 }
37403 {
37404 wuffs_base__status z = wuffs_adler32__hasher__initialize(
37405 &self->private_data.f_dict_id_hasher, sizeof(self->private_data.f_dict_id_hasher), WUFFS_VERSION, options);
37406 if (z.repr) {
37407 return z;
37408 }
37409 }
37410 {
37411 wuffs_base__status z = wuffs_deflate__decoder__initialize(
37412 &self->private_data.f_flate, sizeof(self->private_data.f_flate), WUFFS_VERSION, options);
37413 if (z.repr) {
37414 return z;
37415 }
37416 }
37417 self->private_impl.magic = WUFFS_BASE__MAGIC;
37418 self->private_impl.vtable_for__wuffs_base__io_transformer.vtable_name =
37419 wuffs_base__io_transformer__vtable_name;
37420 self->private_impl.vtable_for__wuffs_base__io_transformer.function_pointers =
37421 (const void*)(&wuffs_zlib__decoder__func_ptrs_for__wuffs_base__io_transformer);
37422 return wuffs_base__make_status(NULL);
37423}
37424
37425wuffs_zlib__decoder*
37426wuffs_zlib__decoder__alloc() {
37427 wuffs_zlib__decoder* x =
37428 (wuffs_zlib__decoder*)(calloc(sizeof(wuffs_zlib__decoder), 1));
37429 if (!x) {
37430 return NULL;
37431 }
37432 if (wuffs_zlib__decoder__initialize(
37433 x, sizeof(wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
37434 free(x);
37435 return NULL;
37436 }
37437 return x;
37438}
37439
37440size_t
37441sizeof__wuffs_zlib__decoder() {
37442 return sizeof(wuffs_zlib__decoder);
37443}
37444
37445// ---------------- Function Implementations
37446
37447// -------- func zlib.decoder.dictionary_id
37448
37449WUFFS_BASE__MAYBE_STATIC uint32_t
37450wuffs_zlib__decoder__dictionary_id(
37451 const wuffs_zlib__decoder* self) {
37452 if (!self) {
37453 return 0;
37454 }
37455 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37456 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37457 return 0;
37458 }
37459
37460 return self->private_impl.f_dict_id_want;
37461}
37462
37463// -------- func zlib.decoder.add_dictionary
37464
37465WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
37466wuffs_zlib__decoder__add_dictionary(
37467 wuffs_zlib__decoder* self,
37468 wuffs_base__slice_u8 a_dict) {
37469 if (!self) {
37470 return wuffs_base__make_empty_struct();
37471 }
37472 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37473 return wuffs_base__make_empty_struct();
37474 }
37475
37476 if (self->private_impl.f_header_complete) {
37477 self->private_impl.f_bad_call_sequence = true;
37478 } else {
37479 self->private_impl.f_dict_id_got = wuffs_adler32__hasher__update_u32(&self->private_data.f_dict_id_hasher, a_dict);
37480 wuffs_deflate__decoder__add_history(&self->private_data.f_flate, a_dict);
37481 }
37482 self->private_impl.f_got_dictionary = true;
37483 return wuffs_base__make_empty_struct();
37484}
37485
37486// -------- func zlib.decoder.set_quirk_enabled
37487
37488WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
37489wuffs_zlib__decoder__set_quirk_enabled(
37490 wuffs_zlib__decoder* self,
37491 uint32_t a_quirk,
37492 bool a_enabled) {
37493 if (!self) {
37494 return wuffs_base__make_empty_struct();
37495 }
37496 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37497 return wuffs_base__make_empty_struct();
37498 }
37499
Nigel Taoebbecaa2022-01-08 14:08:27 +110037500 if (self->private_impl.f_header_complete) {
37501 self->private_impl.f_bad_call_sequence = true;
37502 } else if (a_quirk == 1) {
Nigel Taoe360a532021-04-05 22:47:03 +100037503 self->private_impl.f_ignore_checksum = a_enabled;
Nigel Taoebbecaa2022-01-08 14:08:27 +110037504 } else if (a_quirk >= 2113790976) {
37505 a_quirk -= 2113790976;
37506 if (a_quirk < 1) {
37507 self->private_impl.f_quirks[a_quirk] = a_enabled;
37508 }
Nigel Taoe360a532021-04-05 22:47:03 +100037509 }
37510 return wuffs_base__make_empty_struct();
37511}
37512
37513// -------- func zlib.decoder.workbuf_len
37514
37515WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
37516wuffs_zlib__decoder__workbuf_len(
37517 const wuffs_zlib__decoder* self) {
37518 if (!self) {
37519 return wuffs_base__utility__empty_range_ii_u64();
37520 }
37521 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
37522 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
37523 return wuffs_base__utility__empty_range_ii_u64();
37524 }
37525
37526 return wuffs_base__utility__make_range_ii_u64(1, 1);
37527}
37528
37529// -------- func zlib.decoder.transform_io
37530
37531WUFFS_BASE__MAYBE_STATIC wuffs_base__status
37532wuffs_zlib__decoder__transform_io(
37533 wuffs_zlib__decoder* self,
37534 wuffs_base__io_buffer* a_dst,
37535 wuffs_base__io_buffer* a_src,
37536 wuffs_base__slice_u8 a_workbuf) {
37537 if (!self) {
37538 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
37539 }
37540 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
37541 return wuffs_base__make_status(
37542 (self->private_impl.magic == WUFFS_BASE__DISABLED)
37543 ? wuffs_base__error__disabled_by_previous_error
37544 : wuffs_base__error__initialize_not_called);
37545 }
37546 if (!a_dst || !a_src) {
37547 self->private_impl.magic = WUFFS_BASE__DISABLED;
37548 return wuffs_base__make_status(wuffs_base__error__bad_argument);
37549 }
37550 if ((self->private_impl.active_coroutine != 0) &&
37551 (self->private_impl.active_coroutine != 1)) {
37552 self->private_impl.magic = WUFFS_BASE__DISABLED;
37553 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
37554 }
37555 self->private_impl.active_coroutine = 0;
37556 wuffs_base__status status = wuffs_base__make_status(NULL);
37557
37558 uint16_t v_x = 0;
37559 uint32_t v_checksum_got = 0;
37560 wuffs_base__status v_status = wuffs_base__make_status(NULL);
37561 uint32_t v_checksum_want = 0;
37562 uint64_t v_mark = 0;
37563
37564 uint8_t* iop_a_dst = NULL;
37565 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37566 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37567 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110037568 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037569 io0_a_dst = a_dst->data.ptr;
37570 io1_a_dst = io0_a_dst + a_dst->meta.wi;
37571 iop_a_dst = io1_a_dst;
37572 io2_a_dst = io0_a_dst + a_dst->data.len;
37573 if (a_dst->meta.closed) {
37574 io2_a_dst = iop_a_dst;
37575 }
37576 }
37577 const uint8_t* iop_a_src = NULL;
37578 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37579 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
37580 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110037581 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037582 io0_a_src = a_src->data.ptr;
37583 io1_a_src = io0_a_src + a_src->meta.ri;
37584 iop_a_src = io1_a_src;
37585 io2_a_src = io0_a_src + a_src->meta.wi;
37586 }
37587
37588 uint32_t coro_susp_point = self->private_impl.p_transform_io[0];
37589 if (coro_susp_point) {
37590 v_checksum_got = self->private_data.s_transform_io[0].v_checksum_got;
37591 }
37592 switch (coro_susp_point) {
37593 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
37594
37595 if (self->private_impl.f_bad_call_sequence) {
37596 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
37597 goto exit;
Nigel Taoebbecaa2022-01-08 14:08:27 +110037598 } else if (self->private_impl.f_quirks[0]) {
Nigel Taoe360a532021-04-05 22:47:03 +100037599 } else if ( ! self->private_impl.f_want_dictionary) {
37600 {
37601 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
37602 uint16_t t_0;
37603 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
37604 t_0 = wuffs_base__peek_u16be__no_bounds_check(iop_a_src);
37605 iop_a_src += 2;
37606 } else {
37607 self->private_data.s_transform_io[0].scratch = 0;
37608 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
37609 while (true) {
37610 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37611 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37612 goto suspend;
37613 }
37614 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
37615 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
37616 *scratch >>= 8;
37617 *scratch <<= 8;
37618 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
37619 if (num_bits_0 == 8) {
37620 t_0 = ((uint16_t)(*scratch >> 48));
37621 break;
37622 }
37623 num_bits_0 += 8;
37624 *scratch |= ((uint64_t)(num_bits_0));
37625 }
37626 }
37627 v_x = t_0;
37628 }
37629 if (((v_x >> 8) & 15) != 8) {
37630 status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_method);
37631 goto exit;
37632 }
37633 if ((v_x >> 12) > 7) {
37634 status = wuffs_base__make_status(wuffs_zlib__error__bad_compression_window_size);
37635 goto exit;
37636 }
37637 if ((v_x % 31) != 0) {
37638 status = wuffs_base__make_status(wuffs_zlib__error__bad_parity_check);
37639 goto exit;
37640 }
37641 self->private_impl.f_want_dictionary = ((v_x & 32) != 0);
37642 if (self->private_impl.f_want_dictionary) {
37643 self->private_impl.f_dict_id_got = 1;
37644 {
37645 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
37646 uint32_t t_1;
37647 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
37648 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37649 iop_a_src += 4;
37650 } else {
37651 self->private_data.s_transform_io[0].scratch = 0;
37652 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
37653 while (true) {
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 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
37659 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
37660 *scratch >>= 8;
37661 *scratch <<= 8;
37662 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
37663 if (num_bits_1 == 24) {
37664 t_1 = ((uint32_t)(*scratch >> 32));
37665 break;
37666 }
37667 num_bits_1 += 8;
37668 *scratch |= ((uint64_t)(num_bits_1));
37669 }
37670 }
37671 self->private_impl.f_dict_id_want = t_1;
37672 }
37673 status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required);
37674 goto ok;
37675 } else if (self->private_impl.f_got_dictionary) {
37676 status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary);
37677 goto exit;
37678 }
37679 } else if (self->private_impl.f_dict_id_got != self->private_impl.f_dict_id_want) {
37680 if (self->private_impl.f_got_dictionary) {
37681 status = wuffs_base__make_status(wuffs_zlib__error__incorrect_dictionary);
37682 goto exit;
37683 }
37684 status = wuffs_base__make_status(wuffs_zlib__note__dictionary_required);
37685 goto ok;
37686 }
37687 self->private_impl.f_header_complete = true;
37688 while (true) {
37689 v_mark = ((uint64_t)(iop_a_dst - io0_a_dst));
37690 {
37691 if (a_dst) {
37692 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
37693 }
37694 if (a_src) {
37695 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37696 }
37697 wuffs_base__status t_2 = wuffs_deflate__decoder__transform_io(&self->private_data.f_flate, a_dst, a_src, a_workbuf);
37698 v_status = t_2;
37699 if (a_dst) {
37700 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
37701 }
37702 if (a_src) {
37703 iop_a_src = a_src->data.ptr + a_src->meta.ri;
37704 }
37705 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110037706 if ( ! self->private_impl.f_ignore_checksum && ! self->private_impl.f_quirks[0]) {
Nigel Taoe360a532021-04-05 22:47:03 +100037707 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));
37708 }
37709 if (wuffs_base__status__is_ok(&v_status)) {
37710 goto label__0__break;
37711 }
37712 status = v_status;
37713 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
37714 }
37715 label__0__break:;
Nigel Taoebbecaa2022-01-08 14:08:27 +110037716 if ( ! self->private_impl.f_quirks[0]) {
37717 {
37718 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
37719 uint32_t t_3;
37720 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
37721 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
37722 iop_a_src += 4;
37723 } else {
37724 self->private_data.s_transform_io[0].scratch = 0;
37725 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
37726 while (true) {
37727 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
37728 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
37729 goto suspend;
37730 }
37731 uint64_t* scratch = &self->private_data.s_transform_io[0].scratch;
37732 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
37733 *scratch >>= 8;
37734 *scratch <<= 8;
37735 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
37736 if (num_bits_3 == 24) {
37737 t_3 = ((uint32_t)(*scratch >> 32));
37738 break;
37739 }
37740 num_bits_3 += 8;
37741 *scratch |= ((uint64_t)(num_bits_3));
Nigel Taoe360a532021-04-05 22:47:03 +100037742 }
Nigel Taoe360a532021-04-05 22:47:03 +100037743 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110037744 v_checksum_want = t_3;
Nigel Taoe360a532021-04-05 22:47:03 +100037745 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110037746 if ( ! self->private_impl.f_ignore_checksum && (v_checksum_got != v_checksum_want)) {
37747 status = wuffs_base__make_status(wuffs_zlib__error__bad_checksum);
37748 goto exit;
37749 }
Nigel Taoe360a532021-04-05 22:47:03 +100037750 }
37751
Nigel Taoe360a532021-04-05 22:47:03 +100037752 ok:
37753 self->private_impl.p_transform_io[0] = 0;
37754 goto exit;
37755 }
37756
37757 goto suspend;
37758 suspend:
37759 self->private_impl.p_transform_io[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
37760 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
37761 self->private_data.s_transform_io[0].v_checksum_got = v_checksum_got;
37762
37763 goto exit;
37764 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110037765 if (a_dst && a_dst->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037766 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
37767 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110037768 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100037769 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
37770 }
37771
37772 if (wuffs_base__status__is_error(&status)) {
37773 self->private_impl.magic = WUFFS_BASE__DISABLED;
37774 }
37775 return status;
37776}
37777
37778#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__ZLIB)
37779
37780#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
37781
37782// ---------------- Status Codes Implementations
37783
Nigel Taobf9dab32021-11-18 19:19:55 +110037784const char wuffs_png__error__bad_animation_sequence_number[] = "#png: bad animation sequence number";
Nigel Taoe360a532021-04-05 22:47:03 +100037785const char wuffs_png__error__bad_checksum[] = "#png: bad checksum";
37786const char wuffs_png__error__bad_chunk[] = "#png: bad chunk";
37787const char wuffs_png__error__bad_filter[] = "#png: bad filter";
37788const char wuffs_png__error__bad_header[] = "#png: bad header";
Nigel Taobf9dab32021-11-18 19:19:55 +110037789const char wuffs_png__error__bad_text_chunk_not_latin_1[] = "#png: bad text chunk (not Latin-1)";
Nigel Taoe360a532021-04-05 22:47:03 +100037790const char wuffs_png__error__missing_palette[] = "#png: missing palette";
Nigel Tao123a5c62022-06-03 14:17:20 +100037791const char wuffs_png__error__unsupported_cgbi_extension[] = "#png: unsupported CgBI extension";
Nigel Taobf9dab32021-11-18 19:19:55 +110037792const char wuffs_png__error__unsupported_png_compression_method[] = "#png: unsupported PNG compression method";
Nigel Taoe360a532021-04-05 22:47:03 +100037793const char wuffs_png__error__unsupported_png_file[] = "#png: unsupported PNG file";
Nigel Taobf9dab32021-11-18 19:19:55 +110037794const char wuffs_png__error__internal_error_inconsistent_i_o[] = "#png: internal error: inconsistent I/O";
37795const char wuffs_png__error__internal_error_inconsistent_chunk_type[] = "#png: internal error: inconsistent chunk type";
37796const char wuffs_png__error__internal_error_inconsistent_frame_bounds[] = "#png: internal error: inconsistent frame bounds";
Nigel Taoe360a532021-04-05 22:47:03 +100037797const char wuffs_png__error__internal_error_inconsistent_workbuf_length[] = "#png: internal error: inconsistent workbuf length";
37798const char wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input[] = "#png: internal error: zlib decoder did not exhaust its input";
37799
37800// ---------------- Private Consts
37801
Nigel Taobf9dab32021-11-18 19:19:55 +110037802#define WUFFS_PNG__ANCILLARY_BIT 32
37803
Nigel Taoe360a532021-04-05 22:47:03 +100037804static const uint8_t
37805WUFFS_PNG__INTERLACING[8][6] WUFFS_BASE__POTENTIALLY_UNUSED = {
37806 {
37807 0, 0, 0, 0, 0, 0,
37808 }, {
37809 3, 7, 0, 3, 7, 0,
37810 }, {
37811 3, 3, 4, 3, 7, 0,
37812 }, {
37813 2, 3, 0, 3, 3, 4,
37814 }, {
37815 2, 1, 2, 2, 3, 0,
37816 }, {
37817 1, 1, 0, 2, 1, 2,
37818 }, {
37819 1, 0, 1, 1, 1, 0,
37820 }, {
37821 0, 0, 0, 1, 0, 1,
37822 },
37823};
37824
37825static const uint8_t
37826WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
37827 0, 255, 85, 0, 17, 0, 0, 0,
37828};
37829
37830static const uint8_t
37831WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
37832 0, 8, 4, 0, 2, 0, 0, 0,
37833};
37834
37835static const uint8_t
37836WUFFS_PNG__NUM_CHANNELS[8] WUFFS_BASE__POTENTIALLY_UNUSED = {
37837 1, 0, 3, 1, 2, 0, 4, 0,
37838};
37839
Nigel Taobf9dab32021-11-18 19:19:55 +110037840static const uint16_t
37841WUFFS_PNG__LATIN_1[256] WUFFS_BASE__POTENTIALLY_UNUSED = {
37842 0, 0, 0, 0, 0, 0, 0, 0,
37843 0, 0, 0, 0, 0, 0, 0, 0,
37844 0, 0, 0, 0, 0, 0, 0, 0,
37845 0, 0, 0, 0, 0, 0, 0, 0,
37846 32, 33, 34, 35, 36, 37, 38, 39,
37847 40, 41, 42, 43, 44, 45, 46, 47,
37848 48, 49, 50, 51, 52, 53, 54, 55,
37849 56, 57, 58, 59, 60, 61, 62, 63,
37850 64, 65, 66, 67, 68, 69, 70, 71,
37851 72, 73, 74, 75, 76, 77, 78, 79,
37852 80, 81, 82, 83, 84, 85, 86, 87,
37853 88, 89, 90, 91, 92, 93, 94, 95,
37854 96, 97, 98, 99, 100, 101, 102, 103,
37855 104, 105, 106, 107, 108, 109, 110, 111,
37856 112, 113, 114, 115, 116, 117, 118, 119,
37857 120, 121, 122, 123, 124, 125, 126, 0,
37858 0, 0, 0, 0, 0, 0, 0, 0,
37859 0, 0, 0, 0, 0, 0, 0, 0,
37860 0, 0, 0, 0, 0, 0, 0, 0,
37861 0, 0, 0, 0, 0, 0, 0, 0,
37862 0, 41410, 41666, 41922, 42178, 42434, 42690, 42946,
37863 43202, 43458, 43714, 43970, 44226, 44482, 44738, 44994,
37864 45250, 45506, 45762, 46018, 46274, 46530, 46786, 47042,
37865 47298, 47554, 47810, 48066, 48322, 48578, 48834, 49090,
37866 32963, 33219, 33475, 33731, 33987, 34243, 34499, 34755,
37867 35011, 35267, 35523, 35779, 36035, 36291, 36547, 36803,
37868 37059, 37315, 37571, 37827, 38083, 38339, 38595, 38851,
37869 39107, 39363, 39619, 39875, 40131, 40387, 40643, 40899,
37870 41155, 41411, 41667, 41923, 42179, 42435, 42691, 42947,
37871 43203, 43459, 43715, 43971, 44227, 44483, 44739, 44995,
37872 45251, 45507, 45763, 46019, 46275, 46531, 46787, 47043,
37873 47299, 47555, 47811, 48067, 48323, 48579, 48835, 49091,
37874};
37875
Nigel Taoe360a532021-04-05 22:47:03 +100037876// ---------------- Private Initializer Prototypes
37877
37878// ---------------- Private Function Prototypes
37879
37880#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37881static wuffs_base__empty_struct
37882wuffs_png__decoder__filter_1_distance_4_arm_neon(
37883 wuffs_png__decoder* self,
37884 wuffs_base__slice_u8 a_curr);
37885#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37886
37887#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37888static wuffs_base__empty_struct
37889wuffs_png__decoder__filter_3_distance_4_arm_neon(
37890 wuffs_png__decoder* self,
37891 wuffs_base__slice_u8 a_curr,
37892 wuffs_base__slice_u8 a_prev);
37893#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37894
37895#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37896static wuffs_base__empty_struct
37897wuffs_png__decoder__filter_4_distance_3_arm_neon(
37898 wuffs_png__decoder* self,
37899 wuffs_base__slice_u8 a_curr,
37900 wuffs_base__slice_u8 a_prev);
37901#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37902
37903#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37904static wuffs_base__empty_struct
37905wuffs_png__decoder__filter_4_distance_4_arm_neon(
37906 wuffs_png__decoder* self,
37907 wuffs_base__slice_u8 a_curr,
37908 wuffs_base__slice_u8 a_prev);
37909#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
37910
37911static wuffs_base__empty_struct
37912wuffs_png__decoder__filter_1(
37913 wuffs_png__decoder* self,
37914 wuffs_base__slice_u8 a_curr);
37915
37916static wuffs_base__empty_struct
37917wuffs_png__decoder__filter_1__choosy_default(
37918 wuffs_png__decoder* self,
37919 wuffs_base__slice_u8 a_curr);
37920
37921static wuffs_base__empty_struct
37922wuffs_png__decoder__filter_1_distance_3_fallback(
37923 wuffs_png__decoder* self,
37924 wuffs_base__slice_u8 a_curr);
37925
37926static wuffs_base__empty_struct
37927wuffs_png__decoder__filter_1_distance_4_fallback(
37928 wuffs_png__decoder* self,
37929 wuffs_base__slice_u8 a_curr);
37930
37931static wuffs_base__empty_struct
37932wuffs_png__decoder__filter_2(
37933 wuffs_png__decoder* self,
37934 wuffs_base__slice_u8 a_curr,
37935 wuffs_base__slice_u8 a_prev);
37936
37937static wuffs_base__empty_struct
37938wuffs_png__decoder__filter_3(
37939 wuffs_png__decoder* self,
37940 wuffs_base__slice_u8 a_curr,
37941 wuffs_base__slice_u8 a_prev);
37942
37943static wuffs_base__empty_struct
37944wuffs_png__decoder__filter_3__choosy_default(
37945 wuffs_png__decoder* self,
37946 wuffs_base__slice_u8 a_curr,
37947 wuffs_base__slice_u8 a_prev);
37948
37949static wuffs_base__empty_struct
37950wuffs_png__decoder__filter_3_distance_3_fallback(
37951 wuffs_png__decoder* self,
37952 wuffs_base__slice_u8 a_curr,
37953 wuffs_base__slice_u8 a_prev);
37954
37955static wuffs_base__empty_struct
37956wuffs_png__decoder__filter_3_distance_4_fallback(
37957 wuffs_png__decoder* self,
37958 wuffs_base__slice_u8 a_curr,
37959 wuffs_base__slice_u8 a_prev);
37960
37961static wuffs_base__empty_struct
37962wuffs_png__decoder__filter_4(
37963 wuffs_png__decoder* self,
37964 wuffs_base__slice_u8 a_curr,
37965 wuffs_base__slice_u8 a_prev);
37966
37967static wuffs_base__empty_struct
37968wuffs_png__decoder__filter_4__choosy_default(
37969 wuffs_png__decoder* self,
37970 wuffs_base__slice_u8 a_curr,
37971 wuffs_base__slice_u8 a_prev);
37972
37973static wuffs_base__empty_struct
37974wuffs_png__decoder__filter_4_distance_3_fallback(
37975 wuffs_png__decoder* self,
37976 wuffs_base__slice_u8 a_curr,
37977 wuffs_base__slice_u8 a_prev);
37978
37979static wuffs_base__empty_struct
37980wuffs_png__decoder__filter_4_distance_4_fallback(
37981 wuffs_png__decoder* self,
37982 wuffs_base__slice_u8 a_curr,
37983 wuffs_base__slice_u8 a_prev);
37984
Nigel Tao7804ffe2021-10-07 21:58:26 +110037985#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037986static wuffs_base__empty_struct
37987wuffs_png__decoder__filter_1_distance_4_x86_sse42(
37988 wuffs_png__decoder* self,
37989 wuffs_base__slice_u8 a_curr);
Nigel Tao7804ffe2021-10-07 21:58:26 +110037990#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037991
Nigel Tao7804ffe2021-10-07 21:58:26 +110037992#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037993static wuffs_base__empty_struct
37994wuffs_png__decoder__filter_3_distance_4_x86_sse42(
37995 wuffs_png__decoder* self,
37996 wuffs_base__slice_u8 a_curr,
37997 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110037998#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100037999
Nigel Tao7804ffe2021-10-07 21:58:26 +110038000#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100038001static wuffs_base__empty_struct
38002wuffs_png__decoder__filter_4_distance_3_x86_sse42(
38003 wuffs_png__decoder* self,
38004 wuffs_base__slice_u8 a_curr,
38005 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110038006#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100038007
Nigel Tao7804ffe2021-10-07 21:58:26 +110038008#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100038009static wuffs_base__empty_struct
38010wuffs_png__decoder__filter_4_distance_4_x86_sse42(
38011 wuffs_png__decoder* self,
38012 wuffs_base__slice_u8 a_curr,
38013 wuffs_base__slice_u8 a_prev);
Nigel Tao7804ffe2021-10-07 21:58:26 +110038014#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100038015
38016static wuffs_base__status
38017wuffs_png__decoder__decode_ihdr(
38018 wuffs_png__decoder* self,
38019 wuffs_base__io_buffer* a_src);
38020
38021static wuffs_base__empty_struct
38022wuffs_png__decoder__assign_filter_distance(
38023 wuffs_png__decoder* self);
38024
38025static uint64_t
38026wuffs_png__decoder__calculate_bytes_per_row(
38027 const wuffs_png__decoder* self,
38028 uint32_t a_width);
38029
38030static wuffs_base__empty_struct
38031wuffs_png__decoder__choose_filter_implementations(
38032 wuffs_png__decoder* self);
38033
38034static wuffs_base__status
38035wuffs_png__decoder__decode_other_chunk(
38036 wuffs_png__decoder* self,
Nigel Tao123a5c62022-06-03 14:17:20 +100038037 wuffs_base__io_buffer* a_src,
38038 bool a_framy);
Nigel Taoe360a532021-04-05 22:47:03 +100038039
38040static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110038041wuffs_png__decoder__decode_actl(
38042 wuffs_png__decoder* self,
38043 wuffs_base__io_buffer* a_src);
38044
38045static wuffs_base__status
38046wuffs_png__decoder__decode_chrm(
38047 wuffs_png__decoder* self,
38048 wuffs_base__io_buffer* a_src);
38049
38050static wuffs_base__status
Nigel Taoebbecaa2022-01-08 14:08:27 +110038051wuffs_png__decoder__decode_exif(
38052 wuffs_png__decoder* self,
38053 wuffs_base__io_buffer* a_src);
38054
38055static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110038056wuffs_png__decoder__decode_fctl(
38057 wuffs_png__decoder* self,
38058 wuffs_base__io_buffer* a_src);
38059
38060static wuffs_base__status
38061wuffs_png__decoder__decode_gama(
38062 wuffs_png__decoder* self,
38063 wuffs_base__io_buffer* a_src);
38064
38065static wuffs_base__status
38066wuffs_png__decoder__decode_iccp(
38067 wuffs_png__decoder* self,
38068 wuffs_base__io_buffer* a_src);
38069
38070static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100038071wuffs_png__decoder__decode_plte(
38072 wuffs_png__decoder* self,
38073 wuffs_base__io_buffer* a_src);
38074
38075static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110038076wuffs_png__decoder__decode_srgb(
38077 wuffs_png__decoder* self,
38078 wuffs_base__io_buffer* a_src);
38079
38080static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100038081wuffs_png__decoder__decode_trns(
38082 wuffs_png__decoder* self,
38083 wuffs_base__io_buffer* a_src);
38084
38085static wuffs_base__status
Nigel Taobf9dab32021-11-18 19:19:55 +110038086wuffs_png__decoder__skip_frame(
38087 wuffs_png__decoder* self,
38088 wuffs_base__io_buffer* a_src);
38089
38090static wuffs_base__status
Nigel Taoe360a532021-04-05 22:47:03 +100038091wuffs_png__decoder__decode_pass(
38092 wuffs_png__decoder* self,
38093 wuffs_base__io_buffer* a_src,
38094 wuffs_base__slice_u8 a_workbuf);
38095
38096static wuffs_base__status
38097wuffs_png__decoder__filter_and_swizzle(
38098 wuffs_png__decoder* self,
38099 wuffs_base__pixel_buffer* a_dst,
38100 wuffs_base__slice_u8 a_workbuf);
38101
38102static wuffs_base__status
38103wuffs_png__decoder__filter_and_swizzle__choosy_default(
38104 wuffs_png__decoder* self,
38105 wuffs_base__pixel_buffer* a_dst,
38106 wuffs_base__slice_u8 a_workbuf);
38107
38108static wuffs_base__status
38109wuffs_png__decoder__filter_and_swizzle_tricky(
38110 wuffs_png__decoder* self,
38111 wuffs_base__pixel_buffer* a_dst,
38112 wuffs_base__slice_u8 a_workbuf);
38113
38114// ---------------- VTables
38115
38116const wuffs_base__image_decoder__func_ptrs
38117wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder = {
38118 (wuffs_base__status(*)(void*,
38119 wuffs_base__pixel_buffer*,
38120 wuffs_base__io_buffer*,
38121 wuffs_base__pixel_blend,
38122 wuffs_base__slice_u8,
38123 wuffs_base__decode_frame_options*))(&wuffs_png__decoder__decode_frame),
38124 (wuffs_base__status(*)(void*,
38125 wuffs_base__frame_config*,
38126 wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_frame_config),
38127 (wuffs_base__status(*)(void*,
38128 wuffs_base__image_config*,
38129 wuffs_base__io_buffer*))(&wuffs_png__decoder__decode_image_config),
38130 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_png__decoder__frame_dirty_rect),
38131 (uint32_t(*)(const void*))(&wuffs_png__decoder__num_animation_loops),
38132 (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frame_configs),
38133 (uint64_t(*)(const void*))(&wuffs_png__decoder__num_decoded_frames),
38134 (wuffs_base__status(*)(void*,
38135 uint64_t,
38136 uint64_t))(&wuffs_png__decoder__restart_frame),
38137 (wuffs_base__empty_struct(*)(void*,
38138 uint32_t,
38139 bool))(&wuffs_png__decoder__set_quirk_enabled),
38140 (wuffs_base__empty_struct(*)(void*,
38141 uint32_t,
38142 bool))(&wuffs_png__decoder__set_report_metadata),
38143 (wuffs_base__status(*)(void*,
38144 wuffs_base__io_buffer*,
38145 wuffs_base__more_information*,
38146 wuffs_base__io_buffer*))(&wuffs_png__decoder__tell_me_more),
38147 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_png__decoder__workbuf_len),
38148};
38149
38150// ---------------- Initializer Implementations
38151
38152wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
38153wuffs_png__decoder__initialize(
38154 wuffs_png__decoder* self,
38155 size_t sizeof_star_self,
38156 uint64_t wuffs_version,
38157 uint32_t options){
38158 if (!self) {
38159 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
38160 }
38161 if (sizeof(*self) != sizeof_star_self) {
38162 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
38163 }
38164 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
38165 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
38166 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
38167 }
38168
38169 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
38170 // The whole point of this if-check is to detect an uninitialized *self.
38171 // We disable the warning on GCC. Clang-5.0 does not have this warning.
38172#if !defined(__clang__) && defined(__GNUC__)
38173#pragma GCC diagnostic push
38174#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
38175#endif
38176 if (self->private_impl.magic != 0) {
38177 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
38178 }
38179#if !defined(__clang__) && defined(__GNUC__)
38180#pragma GCC diagnostic pop
38181#endif
38182 } else {
38183 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
38184 memset(self, 0, sizeof(*self));
38185 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
38186 } else {
38187 memset(&(self->private_impl), 0, sizeof(self->private_impl));
38188 }
38189 }
38190
38191 self->private_impl.choosy_filter_1 = &wuffs_png__decoder__filter_1__choosy_default;
38192 self->private_impl.choosy_filter_3 = &wuffs_png__decoder__filter_3__choosy_default;
38193 self->private_impl.choosy_filter_4 = &wuffs_png__decoder__filter_4__choosy_default;
38194 self->private_impl.choosy_filter_and_swizzle = &wuffs_png__decoder__filter_and_swizzle__choosy_default;
38195
38196 {
38197 wuffs_base__status z = wuffs_crc32__ieee_hasher__initialize(
38198 &self->private_data.f_crc32, sizeof(self->private_data.f_crc32), WUFFS_VERSION, options);
38199 if (z.repr) {
38200 return z;
38201 }
38202 }
38203 {
38204 wuffs_base__status z = wuffs_zlib__decoder__initialize(
38205 &self->private_data.f_zlib, sizeof(self->private_data.f_zlib), WUFFS_VERSION, options);
38206 if (z.repr) {
38207 return z;
38208 }
38209 }
38210 self->private_impl.magic = WUFFS_BASE__MAGIC;
38211 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
38212 wuffs_base__image_decoder__vtable_name;
38213 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
38214 (const void*)(&wuffs_png__decoder__func_ptrs_for__wuffs_base__image_decoder);
38215 return wuffs_base__make_status(NULL);
38216}
38217
38218wuffs_png__decoder*
38219wuffs_png__decoder__alloc() {
38220 wuffs_png__decoder* x =
38221 (wuffs_png__decoder*)(calloc(sizeof(wuffs_png__decoder), 1));
38222 if (!x) {
38223 return NULL;
38224 }
38225 if (wuffs_png__decoder__initialize(
38226 x, sizeof(wuffs_png__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
38227 free(x);
38228 return NULL;
38229 }
38230 return x;
38231}
38232
38233size_t
38234sizeof__wuffs_png__decoder() {
38235 return sizeof(wuffs_png__decoder);
38236}
38237
38238// ---------------- Function Implementations
38239
38240// ‼ WUFFS MULTI-FILE SECTION +arm_neon
38241// -------- func png.decoder.filter_1_distance_4_arm_neon
38242
38243#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38244static wuffs_base__empty_struct
38245wuffs_png__decoder__filter_1_distance_4_arm_neon(
38246 wuffs_png__decoder* self,
38247 wuffs_base__slice_u8 a_curr) {
38248 wuffs_base__slice_u8 v_curr = {0};
38249 uint8x8_t v_fa = {0};
38250 uint8x8_t v_fx = {0};
38251
38252 {
38253 wuffs_base__slice_u8 i_slice_curr = a_curr;
38254 v_curr.ptr = i_slice_curr.ptr;
38255 v_curr.len = 4;
38256 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
38257 while (v_curr.ptr < i_end0_curr) {
38258 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38259 v_fx = vadd_u8(v_fx, v_fa);
38260 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38261 v_fa = v_fx;
38262 v_curr.ptr += 4;
38263 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38264 v_fx = vadd_u8(v_fx, v_fa);
38265 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38266 v_fa = v_fx;
38267 v_curr.ptr += 4;
38268 }
38269 v_curr.len = 4;
38270 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38271 while (v_curr.ptr < i_end1_curr) {
38272 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38273 v_fx = vadd_u8(v_fx, v_fa);
38274 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38275 v_fa = v_fx;
38276 v_curr.ptr += 4;
38277 }
38278 v_curr.len = 0;
38279 }
38280 return wuffs_base__make_empty_struct();
38281}
38282#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38283// ‼ WUFFS MULTI-FILE SECTION -arm_neon
38284
38285// ‼ WUFFS MULTI-FILE SECTION +arm_neon
38286// -------- func png.decoder.filter_3_distance_4_arm_neon
38287
38288#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38289static wuffs_base__empty_struct
38290wuffs_png__decoder__filter_3_distance_4_arm_neon(
38291 wuffs_png__decoder* self,
38292 wuffs_base__slice_u8 a_curr,
38293 wuffs_base__slice_u8 a_prev) {
38294 wuffs_base__slice_u8 v_curr = {0};
38295 wuffs_base__slice_u8 v_prev = {0};
38296 uint8x8_t v_fa = {0};
38297 uint8x8_t v_fb = {0};
38298 uint8x8_t v_fx = {0};
38299
38300 if (((uint64_t)(a_prev.len)) == 0) {
38301 {
38302 wuffs_base__slice_u8 i_slice_curr = a_curr;
38303 v_curr.ptr = i_slice_curr.ptr;
38304 v_curr.len = 4;
38305 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
38306 while (v_curr.ptr < i_end0_curr) {
38307 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38308 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38309 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38310 v_fa = v_fx;
38311 v_curr.ptr += 4;
38312 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38313 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38314 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38315 v_fa = v_fx;
38316 v_curr.ptr += 4;
38317 }
38318 v_curr.len = 4;
38319 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38320 while (v_curr.ptr < i_end1_curr) {
38321 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38322 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38323 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38324 v_fa = v_fx;
38325 v_curr.ptr += 4;
38326 }
38327 v_curr.len = 0;
38328 }
38329 } else {
38330 {
38331 wuffs_base__slice_u8 i_slice_curr = a_curr;
38332 v_curr.ptr = i_slice_curr.ptr;
38333 wuffs_base__slice_u8 i_slice_prev = a_prev;
38334 v_prev.ptr = i_slice_prev.ptr;
38335 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
38336 v_curr.len = 4;
38337 v_prev.len = 4;
38338 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
38339 while (v_curr.ptr < i_end0_curr) {
38340 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38341 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38342 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38343 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38344 v_fa = v_fx;
38345 v_curr.ptr += 4;
38346 v_prev.ptr += 4;
38347 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38348 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38349 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38350 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38351 v_fa = v_fx;
38352 v_curr.ptr += 4;
38353 v_prev.ptr += 4;
38354 }
38355 v_curr.len = 4;
38356 v_prev.len = 4;
38357 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38358 while (v_curr.ptr < i_end1_curr) {
38359 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38360 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38361 v_fx = vadd_u8(v_fx, vhadd_u8(v_fa, v_fb));
38362 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38363 v_fa = v_fx;
38364 v_curr.ptr += 4;
38365 v_prev.ptr += 4;
38366 }
38367 v_curr.len = 0;
38368 v_prev.len = 0;
38369 }
38370 }
38371 return wuffs_base__make_empty_struct();
38372}
38373#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38374// ‼ WUFFS MULTI-FILE SECTION -arm_neon
38375
38376// ‼ WUFFS MULTI-FILE SECTION +arm_neon
38377// -------- func png.decoder.filter_4_distance_3_arm_neon
38378
38379#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38380static wuffs_base__empty_struct
38381wuffs_png__decoder__filter_4_distance_3_arm_neon(
38382 wuffs_png__decoder* self,
38383 wuffs_base__slice_u8 a_curr,
38384 wuffs_base__slice_u8 a_prev) {
38385 wuffs_base__slice_u8 v_curr = {0};
38386 wuffs_base__slice_u8 v_prev = {0};
38387 uint8x8_t v_fa = {0};
38388 uint8x8_t v_fb = {0};
38389 uint8x8_t v_fc = {0};
38390 uint8x8_t v_fx = {0};
38391 uint16x8_t v_fafb = {0};
38392 uint16x8_t v_fcfc = {0};
38393 uint16x8_t v_pa = {0};
38394 uint16x8_t v_pb = {0};
38395 uint16x8_t v_pc = {0};
38396 uint16x8_t v_cmpab = {0};
38397 uint16x8_t v_cmpac = {0};
38398 uint8x8_t v_picka = {0};
38399 uint8x8_t v_pickb = {0};
38400
38401 {
38402 wuffs_base__slice_u8 i_slice_curr = a_curr;
38403 v_curr.ptr = i_slice_curr.ptr;
38404 wuffs_base__slice_u8 i_slice_prev = a_prev;
38405 v_prev.ptr = i_slice_prev.ptr;
38406 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
38407 v_curr.len = 4;
38408 v_prev.len = 4;
38409 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);
38410 while (v_curr.ptr < i_end0_curr) {
38411 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38412 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38413 v_fafb = vaddl_u8(v_fa, v_fb);
38414 v_fcfc = vaddl_u8(v_fc, v_fc);
38415 v_pa = vabdl_u8(v_fb, v_fc);
38416 v_pb = vabdl_u8(v_fa, v_fc);
38417 v_pc = vabdq_u16(v_fafb, v_fcfc);
38418 v_cmpab = vcleq_u16(v_pa, v_pb);
38419 v_cmpac = vcleq_u16(v_pa, v_pc);
38420 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38421 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38422 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38423 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38424 v_fc = v_fb;
38425 v_fa = v_fx;
38426 v_curr.ptr += 3;
38427 v_prev.ptr += 3;
38428 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38429 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38430 v_fafb = vaddl_u8(v_fa, v_fb);
38431 v_fcfc = vaddl_u8(v_fc, v_fc);
38432 v_pa = vabdl_u8(v_fb, v_fc);
38433 v_pb = vabdl_u8(v_fa, v_fc);
38434 v_pc = vabdq_u16(v_fafb, v_fcfc);
38435 v_cmpab = vcleq_u16(v_pa, v_pb);
38436 v_cmpac = vcleq_u16(v_pa, v_pc);
38437 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38438 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38439 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38440 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38441 v_fc = v_fb;
38442 v_fa = v_fx;
38443 v_curr.ptr += 3;
38444 v_prev.ptr += 3;
38445 }
38446 v_curr.len = 4;
38447 v_prev.len = 4;
38448 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);
38449 while (v_curr.ptr < i_end1_curr) {
38450 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38451 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38452 v_fafb = vaddl_u8(v_fa, v_fb);
38453 v_fcfc = vaddl_u8(v_fc, v_fc);
38454 v_pa = vabdl_u8(v_fb, v_fc);
38455 v_pb = vabdl_u8(v_fa, v_fc);
38456 v_pc = vabdq_u16(v_fafb, v_fcfc);
38457 v_cmpab = vcleq_u16(v_pa, v_pb);
38458 v_cmpac = vcleq_u16(v_pa, v_pc);
38459 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38460 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38461 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38462 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38463 v_fc = v_fb;
38464 v_fa = v_fx;
38465 v_curr.ptr += 3;
38466 v_prev.ptr += 3;
38467 }
38468 v_curr.len = 3;
38469 v_prev.len = 3;
38470 uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
38471 while (v_curr.ptr < i_end2_curr) {
38472 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr)));
38473 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr)));
38474 v_fafb = vaddl_u8(v_fa, v_fb);
38475 v_fcfc = vaddl_u8(v_fc, v_fc);
38476 v_pa = vabdl_u8(v_fb, v_fc);
38477 v_pb = vabdl_u8(v_fa, v_fc);
38478 v_pc = vabdq_u16(v_fafb, v_fcfc);
38479 v_cmpab = vcleq_u16(v_pa, v_pb);
38480 v_cmpac = vcleq_u16(v_pa, v_pc);
38481 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38482 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38483 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38484 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38485 v_curr.ptr += 3;
38486 v_prev.ptr += 3;
38487 }
38488 v_curr.len = 0;
38489 v_prev.len = 0;
38490 }
38491 return wuffs_base__make_empty_struct();
38492}
38493#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38494// ‼ WUFFS MULTI-FILE SECTION -arm_neon
38495
38496// ‼ WUFFS MULTI-FILE SECTION +arm_neon
38497// -------- func png.decoder.filter_4_distance_4_arm_neon
38498
38499#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38500static wuffs_base__empty_struct
38501wuffs_png__decoder__filter_4_distance_4_arm_neon(
38502 wuffs_png__decoder* self,
38503 wuffs_base__slice_u8 a_curr,
38504 wuffs_base__slice_u8 a_prev) {
38505 wuffs_base__slice_u8 v_curr = {0};
38506 wuffs_base__slice_u8 v_prev = {0};
38507 uint8x8_t v_fa = {0};
38508 uint8x8_t v_fb = {0};
38509 uint8x8_t v_fc = {0};
38510 uint8x8_t v_fx = {0};
38511 uint16x8_t v_fafb = {0};
38512 uint16x8_t v_fcfc = {0};
38513 uint16x8_t v_pa = {0};
38514 uint16x8_t v_pb = {0};
38515 uint16x8_t v_pc = {0};
38516 uint16x8_t v_cmpab = {0};
38517 uint16x8_t v_cmpac = {0};
38518 uint8x8_t v_picka = {0};
38519 uint8x8_t v_pickb = {0};
38520
38521 {
38522 wuffs_base__slice_u8 i_slice_curr = a_curr;
38523 v_curr.ptr = i_slice_curr.ptr;
38524 wuffs_base__slice_u8 i_slice_prev = a_prev;
38525 v_prev.ptr = i_slice_prev.ptr;
38526 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
38527 v_curr.len = 4;
38528 v_prev.len = 4;
38529 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
38530 while (v_curr.ptr < i_end0_curr) {
38531 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38532 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38533 v_fafb = vaddl_u8(v_fa, v_fb);
38534 v_fcfc = vaddl_u8(v_fc, v_fc);
38535 v_pa = vabdl_u8(v_fb, v_fc);
38536 v_pb = vabdl_u8(v_fa, v_fc);
38537 v_pc = vabdq_u16(v_fafb, v_fcfc);
38538 v_cmpab = vcleq_u16(v_pa, v_pb);
38539 v_cmpac = vcleq_u16(v_pa, v_pc);
38540 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38541 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38542 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38543 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38544 v_fc = v_fb;
38545 v_fa = v_fx;
38546 v_curr.ptr += 4;
38547 v_prev.ptr += 4;
38548 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38549 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38550 v_fafb = vaddl_u8(v_fa, v_fb);
38551 v_fcfc = vaddl_u8(v_fc, v_fc);
38552 v_pa = vabdl_u8(v_fb, v_fc);
38553 v_pb = vabdl_u8(v_fa, v_fc);
38554 v_pc = vabdq_u16(v_fafb, v_fcfc);
38555 v_cmpab = vcleq_u16(v_pa, v_pb);
38556 v_cmpac = vcleq_u16(v_pa, v_pc);
38557 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38558 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38559 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38560 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38561 v_fc = v_fb;
38562 v_fa = v_fx;
38563 v_curr.ptr += 4;
38564 v_prev.ptr += 4;
38565 }
38566 v_curr.len = 4;
38567 v_prev.len = 4;
38568 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38569 while (v_curr.ptr < i_end1_curr) {
38570 v_fb = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
38571 v_fx = vreinterpret_u8_u32(vdup_n_u32(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
38572 v_fafb = vaddl_u8(v_fa, v_fb);
38573 v_fcfc = vaddl_u8(v_fc, v_fc);
38574 v_pa = vabdl_u8(v_fb, v_fc);
38575 v_pb = vabdl_u8(v_fa, v_fc);
38576 v_pc = vabdq_u16(v_fafb, v_fcfc);
38577 v_cmpab = vcleq_u16(v_pa, v_pb);
38578 v_cmpac = vcleq_u16(v_pa, v_pc);
38579 v_picka = vmovn_u16(vandq_u16(v_cmpab, v_cmpac));
38580 v_pickb = vmovn_u16(vcleq_u16(v_pb, v_pc));
38581 v_fx = vadd_u8(v_fx, vbsl_u8(v_picka, v_fa, vbsl_u8(v_pickb, v_fb, v_fc)));
38582 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, vget_lane_u32(vreinterpret_u32_u8(v_fx), 0));
38583 v_fc = v_fb;
38584 v_fa = v_fx;
38585 v_curr.ptr += 4;
38586 v_prev.ptr += 4;
38587 }
38588 v_curr.len = 0;
38589 v_prev.len = 0;
38590 }
38591 return wuffs_base__make_empty_struct();
38592}
38593#endif // defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
38594// ‼ WUFFS MULTI-FILE SECTION -arm_neon
38595
38596// -------- func png.decoder.filter_1
38597
38598static wuffs_base__empty_struct
38599wuffs_png__decoder__filter_1(
38600 wuffs_png__decoder* self,
38601 wuffs_base__slice_u8 a_curr) {
38602 return (*self->private_impl.choosy_filter_1)(self, a_curr);
38603}
38604
38605static wuffs_base__empty_struct
38606wuffs_png__decoder__filter_1__choosy_default(
38607 wuffs_png__decoder* self,
38608 wuffs_base__slice_u8 a_curr) {
38609 uint64_t v_filter_distance = 0;
38610 uint8_t v_fa = 0;
38611 uint64_t v_i_start = 0;
38612 uint64_t v_i = 0;
38613
38614 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
38615 v_i_start = 0;
38616 while (v_i_start < v_filter_distance) {
38617 v_fa = 0;
38618 v_i = v_i_start;
38619 while (v_i < ((uint64_t)(a_curr.len))) {
38620 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + v_fa));
38621 v_fa = a_curr.ptr[v_i];
38622 v_i += v_filter_distance;
38623 }
38624 v_i_start += 1;
38625 }
38626 return wuffs_base__make_empty_struct();
38627}
38628
38629// -------- func png.decoder.filter_1_distance_3_fallback
38630
38631static wuffs_base__empty_struct
38632wuffs_png__decoder__filter_1_distance_3_fallback(
38633 wuffs_png__decoder* self,
38634 wuffs_base__slice_u8 a_curr) {
38635 wuffs_base__slice_u8 v_curr = {0};
38636 uint8_t v_fa0 = 0;
38637 uint8_t v_fa1 = 0;
38638 uint8_t v_fa2 = 0;
38639
38640 {
38641 wuffs_base__slice_u8 i_slice_curr = a_curr;
38642 v_curr.ptr = i_slice_curr.ptr;
38643 v_curr.len = 3;
38644 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
38645 while (v_curr.ptr < i_end0_curr) {
38646 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
38647 v_curr.ptr[0] = v_fa0;
38648 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
38649 v_curr.ptr[1] = v_fa1;
38650 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
38651 v_curr.ptr[2] = v_fa2;
38652 v_curr.ptr += 3;
38653 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
38654 v_curr.ptr[0] = v_fa0;
38655 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
38656 v_curr.ptr[1] = v_fa1;
38657 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
38658 v_curr.ptr[2] = v_fa2;
38659 v_curr.ptr += 3;
38660 }
38661 v_curr.len = 3;
38662 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
38663 while (v_curr.ptr < i_end1_curr) {
38664 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
38665 v_curr.ptr[0] = v_fa0;
38666 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
38667 v_curr.ptr[1] = v_fa1;
38668 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
38669 v_curr.ptr[2] = v_fa2;
38670 v_curr.ptr += 3;
38671 }
38672 v_curr.len = 0;
38673 }
38674 return wuffs_base__make_empty_struct();
38675}
38676
38677// -------- func png.decoder.filter_1_distance_4_fallback
38678
38679static wuffs_base__empty_struct
38680wuffs_png__decoder__filter_1_distance_4_fallback(
38681 wuffs_png__decoder* self,
38682 wuffs_base__slice_u8 a_curr) {
38683 wuffs_base__slice_u8 v_curr = {0};
38684 uint8_t v_fa0 = 0;
38685 uint8_t v_fa1 = 0;
38686 uint8_t v_fa2 = 0;
38687 uint8_t v_fa3 = 0;
38688
38689 {
38690 wuffs_base__slice_u8 i_slice_curr = a_curr;
38691 v_curr.ptr = i_slice_curr.ptr;
38692 v_curr.len = 4;
38693 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38694 while (v_curr.ptr < i_end0_curr) {
38695 v_fa0 = ((uint8_t)(v_fa0 + v_curr.ptr[0]));
38696 v_curr.ptr[0] = v_fa0;
38697 v_fa1 = ((uint8_t)(v_fa1 + v_curr.ptr[1]));
38698 v_curr.ptr[1] = v_fa1;
38699 v_fa2 = ((uint8_t)(v_fa2 + v_curr.ptr[2]));
38700 v_curr.ptr[2] = v_fa2;
38701 v_fa3 = ((uint8_t)(v_fa3 + v_curr.ptr[3]));
38702 v_curr.ptr[3] = v_fa3;
38703 v_curr.ptr += 4;
38704 }
38705 v_curr.len = 0;
38706 }
38707 return wuffs_base__make_empty_struct();
38708}
38709
38710// -------- func png.decoder.filter_2
38711
38712static wuffs_base__empty_struct
38713wuffs_png__decoder__filter_2(
38714 wuffs_png__decoder* self,
38715 wuffs_base__slice_u8 a_curr,
38716 wuffs_base__slice_u8 a_prev) {
38717 uint64_t v_n = 0;
38718 uint64_t v_i = 0;
38719
38720 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
38721 v_i = 0;
38722 while (v_i < v_n) {
38723 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i]));
38724 v_i += 1;
38725 }
38726 return wuffs_base__make_empty_struct();
38727}
38728
38729// -------- func png.decoder.filter_3
38730
38731static wuffs_base__empty_struct
38732wuffs_png__decoder__filter_3(
38733 wuffs_png__decoder* self,
38734 wuffs_base__slice_u8 a_curr,
38735 wuffs_base__slice_u8 a_prev) {
38736 return (*self->private_impl.choosy_filter_3)(self, a_curr, a_prev);
38737}
38738
38739static wuffs_base__empty_struct
38740wuffs_png__decoder__filter_3__choosy_default(
38741 wuffs_png__decoder* self,
38742 wuffs_base__slice_u8 a_curr,
38743 wuffs_base__slice_u8 a_prev) {
38744 uint64_t v_filter_distance = 0;
38745 uint64_t v_n = 0;
38746 uint64_t v_i = 0;
38747
38748 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
38749 if (((uint64_t)(a_prev.len)) == 0) {
38750 v_i = v_filter_distance;
38751 while (v_i < ((uint64_t)(a_curr.len))) {
38752 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_curr.ptr[(v_i - v_filter_distance)] / 2)));
38753 v_i += 1;
38754 }
38755 } else {
38756 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
38757 v_i = 0;
38758 while ((v_i < v_n) && (v_i < v_filter_distance)) {
38759 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + (a_prev.ptr[v_i] / 2)));
38760 v_i += 1;
38761 }
38762 v_i = v_filter_distance;
38763 while (v_i < v_n) {
38764 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)))));
38765 v_i += 1;
38766 }
38767 }
38768 return wuffs_base__make_empty_struct();
38769}
38770
38771// -------- func png.decoder.filter_3_distance_3_fallback
38772
38773static wuffs_base__empty_struct
38774wuffs_png__decoder__filter_3_distance_3_fallback(
38775 wuffs_png__decoder* self,
38776 wuffs_base__slice_u8 a_curr,
38777 wuffs_base__slice_u8 a_prev) {
38778 wuffs_base__slice_u8 v_curr = {0};
38779 wuffs_base__slice_u8 v_prev = {0};
38780 uint8_t v_fa0 = 0;
38781 uint8_t v_fa1 = 0;
38782 uint8_t v_fa2 = 0;
38783
38784 if (((uint64_t)(a_prev.len)) == 0) {
38785 {
38786 wuffs_base__slice_u8 i_slice_curr = a_curr;
38787 v_curr.ptr = i_slice_curr.ptr;
38788 v_curr.len = 3;
38789 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
38790 while (v_curr.ptr < i_end0_curr) {
38791 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
38792 v_curr.ptr[0] = v_fa0;
38793 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
38794 v_curr.ptr[1] = v_fa1;
38795 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
38796 v_curr.ptr[2] = v_fa2;
38797 v_curr.ptr += 3;
38798 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
38799 v_curr.ptr[0] = v_fa0;
38800 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
38801 v_curr.ptr[1] = v_fa1;
38802 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
38803 v_curr.ptr[2] = v_fa2;
38804 v_curr.ptr += 3;
38805 }
38806 v_curr.len = 3;
38807 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
38808 while (v_curr.ptr < i_end1_curr) {
38809 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
38810 v_curr.ptr[0] = v_fa0;
38811 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
38812 v_curr.ptr[1] = v_fa1;
38813 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
38814 v_curr.ptr[2] = v_fa2;
38815 v_curr.ptr += 3;
38816 }
38817 v_curr.len = 0;
38818 }
38819 } else {
38820 {
38821 wuffs_base__slice_u8 i_slice_curr = a_curr;
38822 v_curr.ptr = i_slice_curr.ptr;
38823 wuffs_base__slice_u8 i_slice_prev = a_prev;
38824 v_prev.ptr = i_slice_prev.ptr;
38825 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
38826 v_curr.len = 3;
38827 v_prev.len = 3;
38828 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 6) * 6);
38829 while (v_curr.ptr < i_end0_curr) {
38830 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
38831 v_curr.ptr[0] = v_fa0;
38832 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
38833 v_curr.ptr[1] = v_fa1;
38834 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
38835 v_curr.ptr[2] = v_fa2;
38836 v_curr.ptr += 3;
38837 v_prev.ptr += 3;
38838 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
38839 v_curr.ptr[0] = v_fa0;
38840 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
38841 v_curr.ptr[1] = v_fa1;
38842 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
38843 v_curr.ptr[2] = v_fa2;
38844 v_curr.ptr += 3;
38845 v_prev.ptr += 3;
38846 }
38847 v_curr.len = 3;
38848 v_prev.len = 3;
38849 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
38850 while (v_curr.ptr < i_end1_curr) {
38851 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
38852 v_curr.ptr[0] = v_fa0;
38853 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
38854 v_curr.ptr[1] = v_fa1;
38855 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
38856 v_curr.ptr[2] = v_fa2;
38857 v_curr.ptr += 3;
38858 v_prev.ptr += 3;
38859 }
38860 v_curr.len = 0;
38861 v_prev.len = 0;
38862 }
38863 }
38864 return wuffs_base__make_empty_struct();
38865}
38866
38867// -------- func png.decoder.filter_3_distance_4_fallback
38868
38869static wuffs_base__empty_struct
38870wuffs_png__decoder__filter_3_distance_4_fallback(
38871 wuffs_png__decoder* self,
38872 wuffs_base__slice_u8 a_curr,
38873 wuffs_base__slice_u8 a_prev) {
38874 wuffs_base__slice_u8 v_curr = {0};
38875 wuffs_base__slice_u8 v_prev = {0};
38876 uint8_t v_fa0 = 0;
38877 uint8_t v_fa1 = 0;
38878 uint8_t v_fa2 = 0;
38879 uint8_t v_fa3 = 0;
38880
38881 if (((uint64_t)(a_prev.len)) == 0) {
38882 {
38883 wuffs_base__slice_u8 i_slice_curr = a_curr;
38884 v_curr.ptr = i_slice_curr.ptr;
38885 v_curr.len = 4;
38886 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38887 while (v_curr.ptr < i_end0_curr) {
38888 v_fa0 = ((uint8_t)((v_fa0 / 2) + v_curr.ptr[0]));
38889 v_curr.ptr[0] = v_fa0;
38890 v_fa1 = ((uint8_t)((v_fa1 / 2) + v_curr.ptr[1]));
38891 v_curr.ptr[1] = v_fa1;
38892 v_fa2 = ((uint8_t)((v_fa2 / 2) + v_curr.ptr[2]));
38893 v_curr.ptr[2] = v_fa2;
38894 v_fa3 = ((uint8_t)((v_fa3 / 2) + v_curr.ptr[3]));
38895 v_curr.ptr[3] = v_fa3;
38896 v_curr.ptr += 4;
38897 }
38898 v_curr.len = 0;
38899 }
38900 } else {
38901 {
38902 wuffs_base__slice_u8 i_slice_curr = a_curr;
38903 v_curr.ptr = i_slice_curr.ptr;
38904 wuffs_base__slice_u8 i_slice_prev = a_prev;
38905 v_prev.ptr = i_slice_prev.ptr;
38906 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
38907 v_curr.len = 4;
38908 v_prev.len = 4;
38909 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
38910 while (v_curr.ptr < i_end0_curr) {
38911 v_fa0 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa0)) + ((uint32_t)(v_prev.ptr[0]))) / 2))) + v_curr.ptr[0]));
38912 v_curr.ptr[0] = v_fa0;
38913 v_fa1 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa1)) + ((uint32_t)(v_prev.ptr[1]))) / 2))) + v_curr.ptr[1]));
38914 v_curr.ptr[1] = v_fa1;
38915 v_fa2 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa2)) + ((uint32_t)(v_prev.ptr[2]))) / 2))) + v_curr.ptr[2]));
38916 v_curr.ptr[2] = v_fa2;
38917 v_fa3 = ((uint8_t)(((uint8_t)(((((uint32_t)(v_fa3)) + ((uint32_t)(v_prev.ptr[3]))) / 2))) + v_curr.ptr[3]));
38918 v_curr.ptr[3] = v_fa3;
38919 v_curr.ptr += 4;
38920 v_prev.ptr += 4;
38921 }
38922 v_curr.len = 0;
38923 v_prev.len = 0;
38924 }
38925 }
38926 return wuffs_base__make_empty_struct();
38927}
38928
38929// -------- func png.decoder.filter_4
38930
38931static wuffs_base__empty_struct
38932wuffs_png__decoder__filter_4(
38933 wuffs_png__decoder* self,
38934 wuffs_base__slice_u8 a_curr,
38935 wuffs_base__slice_u8 a_prev) {
38936 return (*self->private_impl.choosy_filter_4)(self, a_curr, a_prev);
38937}
38938
38939static wuffs_base__empty_struct
38940wuffs_png__decoder__filter_4__choosy_default(
38941 wuffs_png__decoder* self,
38942 wuffs_base__slice_u8 a_curr,
38943 wuffs_base__slice_u8 a_prev) {
38944 uint64_t v_filter_distance = 0;
38945 uint64_t v_n = 0;
38946 uint64_t v_i = 0;
38947 uint32_t v_fa = 0;
38948 uint32_t v_fb = 0;
38949 uint32_t v_fc = 0;
38950 uint32_t v_pp = 0;
38951 uint32_t v_pa = 0;
38952 uint32_t v_pb = 0;
38953 uint32_t v_pc = 0;
38954
38955 v_filter_distance = ((uint64_t)(self->private_impl.f_filter_distance));
38956 v_n = wuffs_base__u64__min(((uint64_t)(a_curr.len)), ((uint64_t)(a_prev.len)));
38957 v_i = 0;
38958 while ((v_i < v_n) && (v_i < v_filter_distance)) {
38959 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + a_prev.ptr[v_i]));
38960 v_i += 1;
38961 }
38962 v_i = v_filter_distance;
38963 while (v_i < v_n) {
38964 v_fa = ((uint32_t)(a_curr.ptr[(v_i - v_filter_distance)]));
38965 v_fb = ((uint32_t)(a_prev.ptr[v_i]));
38966 v_fc = ((uint32_t)(a_prev.ptr[(v_i - v_filter_distance)]));
38967 v_pp = ((uint32_t)(((uint32_t)(v_fa + v_fb)) - v_fc));
38968 v_pa = ((uint32_t)(v_pp - v_fa));
38969 if (v_pa >= 2147483648) {
38970 v_pa = ((uint32_t)(0 - v_pa));
38971 }
38972 v_pb = ((uint32_t)(v_pp - v_fb));
38973 if (v_pb >= 2147483648) {
38974 v_pb = ((uint32_t)(0 - v_pb));
38975 }
38976 v_pc = ((uint32_t)(v_pp - v_fc));
38977 if (v_pc >= 2147483648) {
38978 v_pc = ((uint32_t)(0 - v_pc));
38979 }
38980 if ((v_pa <= v_pb) && (v_pa <= v_pc)) {
38981 } else if (v_pb <= v_pc) {
38982 v_fa = v_fb;
38983 } else {
38984 v_fa = v_fc;
38985 }
38986 a_curr.ptr[v_i] = ((uint8_t)(a_curr.ptr[v_i] + ((uint8_t)((v_fa & 255)))));
38987 v_i += 1;
38988 }
38989 return wuffs_base__make_empty_struct();
38990}
38991
38992// -------- func png.decoder.filter_4_distance_3_fallback
38993
38994static wuffs_base__empty_struct
38995wuffs_png__decoder__filter_4_distance_3_fallback(
38996 wuffs_png__decoder* self,
38997 wuffs_base__slice_u8 a_curr,
38998 wuffs_base__slice_u8 a_prev) {
38999 wuffs_base__slice_u8 v_curr = {0};
39000 wuffs_base__slice_u8 v_prev = {0};
39001 uint32_t v_fa0 = 0;
39002 uint32_t v_fa1 = 0;
39003 uint32_t v_fa2 = 0;
39004 uint32_t v_fb0 = 0;
39005 uint32_t v_fb1 = 0;
39006 uint32_t v_fb2 = 0;
39007 uint32_t v_fc0 = 0;
39008 uint32_t v_fc1 = 0;
39009 uint32_t v_fc2 = 0;
39010 uint32_t v_pp0 = 0;
39011 uint32_t v_pp1 = 0;
39012 uint32_t v_pp2 = 0;
39013 uint32_t v_pa0 = 0;
39014 uint32_t v_pa1 = 0;
39015 uint32_t v_pa2 = 0;
39016 uint32_t v_pb0 = 0;
39017 uint32_t v_pb1 = 0;
39018 uint32_t v_pb2 = 0;
39019 uint32_t v_pc0 = 0;
39020 uint32_t v_pc1 = 0;
39021 uint32_t v_pc2 = 0;
39022
39023 {
39024 wuffs_base__slice_u8 i_slice_curr = a_curr;
39025 v_curr.ptr = i_slice_curr.ptr;
39026 wuffs_base__slice_u8 i_slice_prev = a_prev;
39027 v_prev.ptr = i_slice_prev.ptr;
39028 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
39029 v_curr.len = 3;
39030 v_prev.len = 3;
39031 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
39032 while (v_curr.ptr < i_end0_curr) {
39033 v_fb0 = ((uint32_t)(v_prev.ptr[0]));
39034 v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0));
39035 v_pa0 = ((uint32_t)(v_pp0 - v_fa0));
39036 if (v_pa0 >= 2147483648) {
39037 v_pa0 = ((uint32_t)(0 - v_pa0));
39038 }
39039 v_pb0 = ((uint32_t)(v_pp0 - v_fb0));
39040 if (v_pb0 >= 2147483648) {
39041 v_pb0 = ((uint32_t)(0 - v_pb0));
39042 }
39043 v_pc0 = ((uint32_t)(v_pp0 - v_fc0));
39044 if (v_pc0 >= 2147483648) {
39045 v_pc0 = ((uint32_t)(0 - v_pc0));
39046 }
39047 if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) {
39048 } else if (v_pb0 <= v_pc0) {
39049 v_fa0 = v_fb0;
39050 } else {
39051 v_fa0 = v_fc0;
39052 }
39053 v_curr.ptr[0] = ((uint8_t)(v_curr.ptr[0] + ((uint8_t)((v_fa0 & 255)))));
39054 v_fa0 = ((uint32_t)(v_curr.ptr[0]));
39055 v_fc0 = v_fb0;
39056 v_fb1 = ((uint32_t)(v_prev.ptr[1]));
39057 v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1));
39058 v_pa1 = ((uint32_t)(v_pp1 - v_fa1));
39059 if (v_pa1 >= 2147483648) {
39060 v_pa1 = ((uint32_t)(0 - v_pa1));
39061 }
39062 v_pb1 = ((uint32_t)(v_pp1 - v_fb1));
39063 if (v_pb1 >= 2147483648) {
39064 v_pb1 = ((uint32_t)(0 - v_pb1));
39065 }
39066 v_pc1 = ((uint32_t)(v_pp1 - v_fc1));
39067 if (v_pc1 >= 2147483648) {
39068 v_pc1 = ((uint32_t)(0 - v_pc1));
39069 }
39070 if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) {
39071 } else if (v_pb1 <= v_pc1) {
39072 v_fa1 = v_fb1;
39073 } else {
39074 v_fa1 = v_fc1;
39075 }
39076 v_curr.ptr[1] = ((uint8_t)(v_curr.ptr[1] + ((uint8_t)((v_fa1 & 255)))));
39077 v_fa1 = ((uint32_t)(v_curr.ptr[1]));
39078 v_fc1 = v_fb1;
39079 v_fb2 = ((uint32_t)(v_prev.ptr[2]));
39080 v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2));
39081 v_pa2 = ((uint32_t)(v_pp2 - v_fa2));
39082 if (v_pa2 >= 2147483648) {
39083 v_pa2 = ((uint32_t)(0 - v_pa2));
39084 }
39085 v_pb2 = ((uint32_t)(v_pp2 - v_fb2));
39086 if (v_pb2 >= 2147483648) {
39087 v_pb2 = ((uint32_t)(0 - v_pb2));
39088 }
39089 v_pc2 = ((uint32_t)(v_pp2 - v_fc2));
39090 if (v_pc2 >= 2147483648) {
39091 v_pc2 = ((uint32_t)(0 - v_pc2));
39092 }
39093 if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) {
39094 } else if (v_pb2 <= v_pc2) {
39095 v_fa2 = v_fb2;
39096 } else {
39097 v_fa2 = v_fc2;
39098 }
39099 v_curr.ptr[2] = ((uint8_t)(v_curr.ptr[2] + ((uint8_t)((v_fa2 & 255)))));
39100 v_fa2 = ((uint32_t)(v_curr.ptr[2]));
39101 v_fc2 = v_fb2;
39102 v_curr.ptr += 3;
39103 v_prev.ptr += 3;
39104 }
39105 v_curr.len = 0;
39106 v_prev.len = 0;
39107 }
39108 return wuffs_base__make_empty_struct();
39109}
39110
39111// -------- func png.decoder.filter_4_distance_4_fallback
39112
39113static wuffs_base__empty_struct
39114wuffs_png__decoder__filter_4_distance_4_fallback(
39115 wuffs_png__decoder* self,
39116 wuffs_base__slice_u8 a_curr,
39117 wuffs_base__slice_u8 a_prev) {
39118 wuffs_base__slice_u8 v_curr = {0};
39119 wuffs_base__slice_u8 v_prev = {0};
39120 uint32_t v_fa0 = 0;
39121 uint32_t v_fa1 = 0;
39122 uint32_t v_fa2 = 0;
39123 uint32_t v_fa3 = 0;
39124 uint32_t v_fb0 = 0;
39125 uint32_t v_fb1 = 0;
39126 uint32_t v_fb2 = 0;
39127 uint32_t v_fb3 = 0;
39128 uint32_t v_fc0 = 0;
39129 uint32_t v_fc1 = 0;
39130 uint32_t v_fc2 = 0;
39131 uint32_t v_fc3 = 0;
39132 uint32_t v_pp0 = 0;
39133 uint32_t v_pp1 = 0;
39134 uint32_t v_pp2 = 0;
39135 uint32_t v_pp3 = 0;
39136 uint32_t v_pa0 = 0;
39137 uint32_t v_pa1 = 0;
39138 uint32_t v_pa2 = 0;
39139 uint32_t v_pa3 = 0;
39140 uint32_t v_pb0 = 0;
39141 uint32_t v_pb1 = 0;
39142 uint32_t v_pb2 = 0;
39143 uint32_t v_pb3 = 0;
39144 uint32_t v_pc0 = 0;
39145 uint32_t v_pc1 = 0;
39146 uint32_t v_pc2 = 0;
39147 uint32_t v_pc3 = 0;
39148
39149 {
39150 wuffs_base__slice_u8 i_slice_curr = a_curr;
39151 v_curr.ptr = i_slice_curr.ptr;
39152 wuffs_base__slice_u8 i_slice_prev = a_prev;
39153 v_prev.ptr = i_slice_prev.ptr;
39154 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
39155 v_curr.len = 4;
39156 v_prev.len = 4;
39157 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
39158 while (v_curr.ptr < i_end0_curr) {
39159 v_fb0 = ((uint32_t)(v_prev.ptr[0]));
39160 v_pp0 = ((uint32_t)(((uint32_t)(v_fa0 + v_fb0)) - v_fc0));
39161 v_pa0 = ((uint32_t)(v_pp0 - v_fa0));
39162 if (v_pa0 >= 2147483648) {
39163 v_pa0 = ((uint32_t)(0 - v_pa0));
39164 }
39165 v_pb0 = ((uint32_t)(v_pp0 - v_fb0));
39166 if (v_pb0 >= 2147483648) {
39167 v_pb0 = ((uint32_t)(0 - v_pb0));
39168 }
39169 v_pc0 = ((uint32_t)(v_pp0 - v_fc0));
39170 if (v_pc0 >= 2147483648) {
39171 v_pc0 = ((uint32_t)(0 - v_pc0));
39172 }
39173 if ((v_pa0 <= v_pb0) && (v_pa0 <= v_pc0)) {
39174 } else if (v_pb0 <= v_pc0) {
39175 v_fa0 = v_fb0;
39176 } else {
39177 v_fa0 = v_fc0;
39178 }
39179 v_curr.ptr[0] = ((uint8_t)(v_curr.ptr[0] + ((uint8_t)((v_fa0 & 255)))));
39180 v_fa0 = ((uint32_t)(v_curr.ptr[0]));
39181 v_fc0 = v_fb0;
39182 v_fb1 = ((uint32_t)(v_prev.ptr[1]));
39183 v_pp1 = ((uint32_t)(((uint32_t)(v_fa1 + v_fb1)) - v_fc1));
39184 v_pa1 = ((uint32_t)(v_pp1 - v_fa1));
39185 if (v_pa1 >= 2147483648) {
39186 v_pa1 = ((uint32_t)(0 - v_pa1));
39187 }
39188 v_pb1 = ((uint32_t)(v_pp1 - v_fb1));
39189 if (v_pb1 >= 2147483648) {
39190 v_pb1 = ((uint32_t)(0 - v_pb1));
39191 }
39192 v_pc1 = ((uint32_t)(v_pp1 - v_fc1));
39193 if (v_pc1 >= 2147483648) {
39194 v_pc1 = ((uint32_t)(0 - v_pc1));
39195 }
39196 if ((v_pa1 <= v_pb1) && (v_pa1 <= v_pc1)) {
39197 } else if (v_pb1 <= v_pc1) {
39198 v_fa1 = v_fb1;
39199 } else {
39200 v_fa1 = v_fc1;
39201 }
39202 v_curr.ptr[1] = ((uint8_t)(v_curr.ptr[1] + ((uint8_t)((v_fa1 & 255)))));
39203 v_fa1 = ((uint32_t)(v_curr.ptr[1]));
39204 v_fc1 = v_fb1;
39205 v_fb2 = ((uint32_t)(v_prev.ptr[2]));
39206 v_pp2 = ((uint32_t)(((uint32_t)(v_fa2 + v_fb2)) - v_fc2));
39207 v_pa2 = ((uint32_t)(v_pp2 - v_fa2));
39208 if (v_pa2 >= 2147483648) {
39209 v_pa2 = ((uint32_t)(0 - v_pa2));
39210 }
39211 v_pb2 = ((uint32_t)(v_pp2 - v_fb2));
39212 if (v_pb2 >= 2147483648) {
39213 v_pb2 = ((uint32_t)(0 - v_pb2));
39214 }
39215 v_pc2 = ((uint32_t)(v_pp2 - v_fc2));
39216 if (v_pc2 >= 2147483648) {
39217 v_pc2 = ((uint32_t)(0 - v_pc2));
39218 }
39219 if ((v_pa2 <= v_pb2) && (v_pa2 <= v_pc2)) {
39220 } else if (v_pb2 <= v_pc2) {
39221 v_fa2 = v_fb2;
39222 } else {
39223 v_fa2 = v_fc2;
39224 }
39225 v_curr.ptr[2] = ((uint8_t)(v_curr.ptr[2] + ((uint8_t)((v_fa2 & 255)))));
39226 v_fa2 = ((uint32_t)(v_curr.ptr[2]));
39227 v_fc2 = v_fb2;
39228 v_fb3 = ((uint32_t)(v_prev.ptr[3]));
39229 v_pp3 = ((uint32_t)(((uint32_t)(v_fa3 + v_fb3)) - v_fc3));
39230 v_pa3 = ((uint32_t)(v_pp3 - v_fa3));
39231 if (v_pa3 >= 2147483648) {
39232 v_pa3 = ((uint32_t)(0 - v_pa3));
39233 }
39234 v_pb3 = ((uint32_t)(v_pp3 - v_fb3));
39235 if (v_pb3 >= 2147483648) {
39236 v_pb3 = ((uint32_t)(0 - v_pb3));
39237 }
39238 v_pc3 = ((uint32_t)(v_pp3 - v_fc3));
39239 if (v_pc3 >= 2147483648) {
39240 v_pc3 = ((uint32_t)(0 - v_pc3));
39241 }
39242 if ((v_pa3 <= v_pb3) && (v_pa3 <= v_pc3)) {
39243 } else if (v_pb3 <= v_pc3) {
39244 v_fa3 = v_fb3;
39245 } else {
39246 v_fa3 = v_fc3;
39247 }
39248 v_curr.ptr[3] = ((uint8_t)(v_curr.ptr[3] + ((uint8_t)((v_fa3 & 255)))));
39249 v_fa3 = ((uint32_t)(v_curr.ptr[3]));
39250 v_fc3 = v_fb3;
39251 v_curr.ptr += 4;
39252 v_prev.ptr += 4;
39253 }
39254 v_curr.len = 0;
39255 v_prev.len = 0;
39256 }
39257 return wuffs_base__make_empty_struct();
39258}
39259
39260// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
39261// -------- func png.decoder.filter_1_distance_4_x86_sse42
39262
Nigel Tao7804ffe2021-10-07 21:58:26 +110039263#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039264WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
39265static wuffs_base__empty_struct
39266wuffs_png__decoder__filter_1_distance_4_x86_sse42(
39267 wuffs_png__decoder* self,
39268 wuffs_base__slice_u8 a_curr) {
39269 wuffs_base__slice_u8 v_curr = {0};
39270 __m128i v_x128 = {0};
39271 __m128i v_a128 = {0};
39272
39273 {
39274 wuffs_base__slice_u8 i_slice_curr = a_curr;
39275 v_curr.ptr = i_slice_curr.ptr;
39276 v_curr.len = 4;
39277 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
39278 while (v_curr.ptr < i_end0_curr) {
39279 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39280 v_x128 = _mm_add_epi8(v_x128, v_a128);
39281 v_a128 = v_x128;
39282 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39283 v_curr.ptr += 4;
39284 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39285 v_x128 = _mm_add_epi8(v_x128, v_a128);
39286 v_a128 = v_x128;
39287 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39288 v_curr.ptr += 4;
39289 }
39290 v_curr.len = 4;
39291 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
39292 while (v_curr.ptr < i_end1_curr) {
39293 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39294 v_x128 = _mm_add_epi8(v_x128, v_a128);
39295 v_a128 = v_x128;
39296 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39297 v_curr.ptr += 4;
39298 }
39299 v_curr.len = 0;
39300 }
39301 return wuffs_base__make_empty_struct();
39302}
Nigel Tao7804ffe2021-10-07 21:58:26 +110039303#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039304// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
39305
39306// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
39307// -------- func png.decoder.filter_3_distance_4_x86_sse42
39308
Nigel Tao7804ffe2021-10-07 21:58:26 +110039309#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039310WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
39311static wuffs_base__empty_struct
39312wuffs_png__decoder__filter_3_distance_4_x86_sse42(
39313 wuffs_png__decoder* self,
39314 wuffs_base__slice_u8 a_curr,
39315 wuffs_base__slice_u8 a_prev) {
39316 wuffs_base__slice_u8 v_curr = {0};
39317 wuffs_base__slice_u8 v_prev = {0};
39318 __m128i v_x128 = {0};
39319 __m128i v_a128 = {0};
39320 __m128i v_b128 = {0};
39321 __m128i v_p128 = {0};
39322 __m128i v_k128 = {0};
39323
39324 if (((uint64_t)(a_prev.len)) == 0) {
39325 v_k128 = _mm_set1_epi8((int8_t)(254));
39326 {
39327 wuffs_base__slice_u8 i_slice_curr = a_curr;
39328 v_curr.ptr = i_slice_curr.ptr;
39329 v_curr.len = 4;
39330 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
39331 while (v_curr.ptr < i_end0_curr) {
39332 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
39333 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39334 v_x128 = _mm_add_epi8(v_x128, v_p128);
39335 v_a128 = v_x128;
39336 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39337 v_curr.ptr += 4;
39338 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
39339 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39340 v_x128 = _mm_add_epi8(v_x128, v_p128);
39341 v_a128 = v_x128;
39342 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39343 v_curr.ptr += 4;
39344 }
39345 v_curr.len = 4;
39346 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
39347 while (v_curr.ptr < i_end1_curr) {
39348 v_p128 = _mm_avg_epu8(_mm_and_si128(v_a128, v_k128), v_b128);
39349 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39350 v_x128 = _mm_add_epi8(v_x128, v_p128);
39351 v_a128 = v_x128;
39352 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39353 v_curr.ptr += 4;
39354 }
39355 v_curr.len = 0;
39356 }
39357 } else {
39358 v_k128 = _mm_set1_epi8((int8_t)(1));
39359 {
39360 wuffs_base__slice_u8 i_slice_curr = a_curr;
39361 v_curr.ptr = i_slice_curr.ptr;
39362 wuffs_base__slice_u8 i_slice_prev = a_prev;
39363 v_prev.ptr = i_slice_prev.ptr;
39364 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
39365 v_curr.len = 4;
39366 v_prev.len = 4;
39367 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
39368 while (v_curr.ptr < i_end0_curr) {
39369 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39370 v_p128 = _mm_avg_epu8(v_a128, v_b128);
39371 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
39372 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39373 v_x128 = _mm_add_epi8(v_x128, v_p128);
39374 v_a128 = v_x128;
39375 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39376 v_curr.ptr += 4;
39377 v_prev.ptr += 4;
39378 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39379 v_p128 = _mm_avg_epu8(v_a128, v_b128);
39380 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
39381 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39382 v_x128 = _mm_add_epi8(v_x128, v_p128);
39383 v_a128 = v_x128;
39384 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39385 v_curr.ptr += 4;
39386 v_prev.ptr += 4;
39387 }
39388 v_curr.len = 4;
39389 v_prev.len = 4;
39390 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
39391 while (v_curr.ptr < i_end1_curr) {
39392 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39393 v_p128 = _mm_avg_epu8(v_a128, v_b128);
39394 v_p128 = _mm_sub_epi8(v_p128, _mm_and_si128(v_k128, _mm_xor_si128(v_a128, v_b128)));
39395 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39396 v_x128 = _mm_add_epi8(v_x128, v_p128);
39397 v_a128 = v_x128;
39398 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39399 v_curr.ptr += 4;
39400 v_prev.ptr += 4;
39401 }
39402 v_curr.len = 0;
39403 v_prev.len = 0;
39404 }
39405 }
39406 return wuffs_base__make_empty_struct();
39407}
Nigel Tao7804ffe2021-10-07 21:58:26 +110039408#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039409// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
39410
39411// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
39412// -------- func png.decoder.filter_4_distance_3_x86_sse42
39413
Nigel Tao7804ffe2021-10-07 21:58:26 +110039414#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039415WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
39416static wuffs_base__empty_struct
39417wuffs_png__decoder__filter_4_distance_3_x86_sse42(
39418 wuffs_png__decoder* self,
39419 wuffs_base__slice_u8 a_curr,
39420 wuffs_base__slice_u8 a_prev) {
39421 wuffs_base__slice_u8 v_curr = {0};
39422 wuffs_base__slice_u8 v_prev = {0};
39423 __m128i v_x128 = {0};
39424 __m128i v_a128 = {0};
39425 __m128i v_b128 = {0};
39426 __m128i v_c128 = {0};
39427 __m128i v_p128 = {0};
39428 __m128i v_pa128 = {0};
39429 __m128i v_pb128 = {0};
39430 __m128i v_pc128 = {0};
39431 __m128i v_smallest128 = {0};
39432 __m128i v_z128 = {0};
39433
39434 {
39435 wuffs_base__slice_u8 i_slice_curr = a_curr;
39436 v_curr.ptr = i_slice_curr.ptr;
39437 wuffs_base__slice_u8 i_slice_prev = a_prev;
39438 v_prev.ptr = i_slice_prev.ptr;
39439 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
39440 v_curr.len = 4;
39441 v_prev.len = 4;
39442 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);
39443 while (v_curr.ptr < i_end0_curr) {
39444 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39445 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39446 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39447 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39448 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39449 v_pa128 = _mm_abs_epi16(v_pa128);
39450 v_pb128 = _mm_abs_epi16(v_pb128);
39451 v_pc128 = _mm_abs_epi16(v_pc128);
39452 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39453 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));
39454 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39455 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39456 v_x128 = _mm_add_epi8(v_x128, v_p128);
39457 v_a128 = v_x128;
39458 v_c128 = v_b128;
39459 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39460 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39461 v_curr.ptr += 3;
39462 v_prev.ptr += 3;
39463 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39464 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39465 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39466 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39467 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39468 v_pa128 = _mm_abs_epi16(v_pa128);
39469 v_pb128 = _mm_abs_epi16(v_pb128);
39470 v_pc128 = _mm_abs_epi16(v_pc128);
39471 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39472 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));
39473 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39474 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39475 v_x128 = _mm_add_epi8(v_x128, v_p128);
39476 v_a128 = v_x128;
39477 v_c128 = v_b128;
39478 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39479 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39480 v_curr.ptr += 3;
39481 v_prev.ptr += 3;
39482 }
39483 v_curr.len = 4;
39484 v_prev.len = 4;
39485 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);
39486 while (v_curr.ptr < i_end1_curr) {
39487 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39488 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39489 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39490 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39491 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39492 v_pa128 = _mm_abs_epi16(v_pa128);
39493 v_pb128 = _mm_abs_epi16(v_pb128);
39494 v_pc128 = _mm_abs_epi16(v_pc128);
39495 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39496 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));
39497 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39498 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39499 v_x128 = _mm_add_epi8(v_x128, v_p128);
39500 v_a128 = v_x128;
39501 v_c128 = v_b128;
39502 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39503 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39504 v_curr.ptr += 3;
39505 v_prev.ptr += 3;
39506 }
39507 v_curr.len = 3;
39508 v_prev.len = 3;
39509 uint8_t* i_end2_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 3) * 3);
39510 while (v_curr.ptr < i_end2_curr) {
39511 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_prev.ptr)));
39512 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39513 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39514 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39515 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39516 v_pa128 = _mm_abs_epi16(v_pa128);
39517 v_pb128 = _mm_abs_epi16(v_pb128);
39518 v_pc128 = _mm_abs_epi16(v_pc128);
39519 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39520 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));
39521 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u24le__no_bounds_check(v_curr.ptr)));
39522 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39523 v_x128 = _mm_add_epi8(v_x128, v_p128);
39524 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39525 wuffs_base__poke_u24le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39526 v_curr.ptr += 3;
39527 v_prev.ptr += 3;
39528 }
39529 v_curr.len = 0;
39530 v_prev.len = 0;
39531 }
39532 return wuffs_base__make_empty_struct();
39533}
Nigel Tao7804ffe2021-10-07 21:58:26 +110039534#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039535// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
39536
39537// ‼ WUFFS MULTI-FILE SECTION +x86_sse42
39538// -------- func png.decoder.filter_4_distance_4_x86_sse42
39539
Nigel Tao7804ffe2021-10-07 21:58:26 +110039540#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039541WUFFS_BASE__MAYBE_ATTRIBUTE_TARGET("pclmul,popcnt,sse4.2")
39542static wuffs_base__empty_struct
39543wuffs_png__decoder__filter_4_distance_4_x86_sse42(
39544 wuffs_png__decoder* self,
39545 wuffs_base__slice_u8 a_curr,
39546 wuffs_base__slice_u8 a_prev) {
39547 wuffs_base__slice_u8 v_curr = {0};
39548 wuffs_base__slice_u8 v_prev = {0};
39549 __m128i v_x128 = {0};
39550 __m128i v_a128 = {0};
39551 __m128i v_b128 = {0};
39552 __m128i v_c128 = {0};
39553 __m128i v_p128 = {0};
39554 __m128i v_pa128 = {0};
39555 __m128i v_pb128 = {0};
39556 __m128i v_pc128 = {0};
39557 __m128i v_smallest128 = {0};
39558 __m128i v_z128 = {0};
39559
39560 {
39561 wuffs_base__slice_u8 i_slice_curr = a_curr;
39562 v_curr.ptr = i_slice_curr.ptr;
39563 wuffs_base__slice_u8 i_slice_prev = a_prev;
39564 v_prev.ptr = i_slice_prev.ptr;
39565 i_slice_curr.len = ((size_t)(wuffs_base__u64__min(i_slice_curr.len, i_slice_prev.len)));
39566 v_curr.len = 4;
39567 v_prev.len = 4;
39568 uint8_t* i_end0_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 8) * 8);
39569 while (v_curr.ptr < i_end0_curr) {
39570 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39571 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39572 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39573 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39574 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39575 v_pa128 = _mm_abs_epi16(v_pa128);
39576 v_pb128 = _mm_abs_epi16(v_pb128);
39577 v_pc128 = _mm_abs_epi16(v_pc128);
39578 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39579 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));
39580 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39581 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39582 v_x128 = _mm_add_epi8(v_x128, v_p128);
39583 v_a128 = v_x128;
39584 v_c128 = v_b128;
39585 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39586 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39587 v_curr.ptr += 4;
39588 v_prev.ptr += 4;
39589 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39590 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39591 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39592 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39593 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39594 v_pa128 = _mm_abs_epi16(v_pa128);
39595 v_pb128 = _mm_abs_epi16(v_pb128);
39596 v_pc128 = _mm_abs_epi16(v_pc128);
39597 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39598 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));
39599 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39600 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39601 v_x128 = _mm_add_epi8(v_x128, v_p128);
39602 v_a128 = v_x128;
39603 v_c128 = v_b128;
39604 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39605 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39606 v_curr.ptr += 4;
39607 v_prev.ptr += 4;
39608 }
39609 v_curr.len = 4;
39610 v_prev.len = 4;
39611 uint8_t* i_end1_curr = v_curr.ptr + (((i_slice_curr.len - (size_t)(v_curr.ptr - i_slice_curr.ptr)) / 4) * 4);
39612 while (v_curr.ptr < i_end1_curr) {
39613 v_b128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_prev.ptr)));
39614 v_b128 = _mm_unpacklo_epi8(v_b128, v_z128);
39615 v_pa128 = _mm_sub_epi16(v_b128, v_c128);
39616 v_pb128 = _mm_sub_epi16(v_a128, v_c128);
39617 v_pc128 = _mm_add_epi16(v_pa128, v_pb128);
39618 v_pa128 = _mm_abs_epi16(v_pa128);
39619 v_pb128 = _mm_abs_epi16(v_pb128);
39620 v_pc128 = _mm_abs_epi16(v_pc128);
39621 v_smallest128 = _mm_min_epi16(v_pc128, _mm_min_epi16(v_pb128, v_pa128));
39622 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));
39623 v_x128 = _mm_cvtsi32_si128((int32_t)(wuffs_base__peek_u32le__no_bounds_check(v_curr.ptr)));
39624 v_x128 = _mm_unpacklo_epi8(v_x128, v_z128);
39625 v_x128 = _mm_add_epi8(v_x128, v_p128);
39626 v_a128 = v_x128;
39627 v_c128 = v_b128;
39628 v_x128 = _mm_packus_epi16(v_x128, v_x128);
39629 wuffs_base__poke_u32le__no_bounds_check(v_curr.ptr, ((uint32_t)(_mm_cvtsi128_si32(v_x128))));
39630 v_curr.ptr += 4;
39631 v_prev.ptr += 4;
39632 }
39633 v_curr.len = 0;
39634 v_prev.len = 0;
39635 }
39636 return wuffs_base__make_empty_struct();
39637}
Nigel Tao7804ffe2021-10-07 21:58:26 +110039638#endif // defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100039639// ‼ WUFFS MULTI-FILE SECTION -x86_sse42
39640
39641// -------- func png.decoder.set_quirk_enabled
39642
39643WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
39644wuffs_png__decoder__set_quirk_enabled(
39645 wuffs_png__decoder* self,
39646 uint32_t a_quirk,
39647 bool a_enabled) {
39648 if (!self) {
39649 return wuffs_base__make_empty_struct();
39650 }
39651 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
39652 return wuffs_base__make_empty_struct();
39653 }
39654
39655 if (a_quirk == 1) {
39656 self->private_impl.f_ignore_checksum = a_enabled;
39657 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, a_quirk, a_enabled);
39658 }
39659 return wuffs_base__make_empty_struct();
39660}
39661
39662// -------- func png.decoder.decode_image_config
39663
39664WUFFS_BASE__MAYBE_STATIC wuffs_base__status
39665wuffs_png__decoder__decode_image_config(
39666 wuffs_png__decoder* self,
39667 wuffs_base__image_config* a_dst,
39668 wuffs_base__io_buffer* a_src) {
39669 if (!self) {
39670 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
39671 }
39672 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
39673 return wuffs_base__make_status(
39674 (self->private_impl.magic == WUFFS_BASE__DISABLED)
39675 ? wuffs_base__error__disabled_by_previous_error
39676 : wuffs_base__error__initialize_not_called);
39677 }
39678 if (!a_src) {
39679 self->private_impl.magic = WUFFS_BASE__DISABLED;
39680 return wuffs_base__make_status(wuffs_base__error__bad_argument);
39681 }
39682 if ((self->private_impl.active_coroutine != 0) &&
39683 (self->private_impl.active_coroutine != 1)) {
39684 self->private_impl.magic = WUFFS_BASE__DISABLED;
39685 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
39686 }
39687 self->private_impl.active_coroutine = 0;
39688 wuffs_base__status status = wuffs_base__make_status(NULL);
39689
39690 uint64_t v_magic = 0;
39691 uint64_t v_mark = 0;
39692 uint32_t v_checksum_have = 0;
39693 uint32_t v_checksum_want = 0;
39694 wuffs_base__status v_status = wuffs_base__make_status(NULL);
39695
39696 const uint8_t* iop_a_src = NULL;
39697 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39698 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
39699 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110039700 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100039701 io0_a_src = a_src->data.ptr;
39702 io1_a_src = io0_a_src + a_src->meta.ri;
39703 iop_a_src = io1_a_src;
39704 io2_a_src = io0_a_src + a_src->meta.wi;
39705 }
39706
39707 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
39708 if (coro_susp_point) {
39709 v_checksum_have = self->private_data.s_decode_image_config[0].v_checksum_have;
39710 }
39711 switch (coro_susp_point) {
39712 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
39713
Nigel Tao123a5c62022-06-03 14:17:20 +100039714 if (self->private_impl.f_call_sequence != 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100039715 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
39716 goto exit;
Nigel Tao123a5c62022-06-03 14:17:20 +100039717 } else if ( ! self->private_impl.f_seen_ihdr) {
Nigel Taoe360a532021-04-05 22:47:03 +100039718 {
Nigel Taobf9dab32021-11-18 19:19:55 +110039719 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
39720 uint64_t t_0;
39721 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) {
39722 t_0 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src);
39723 iop_a_src += 8;
Nigel Taoe360a532021-04-05 22:47:03 +100039724 } else {
39725 self->private_data.s_decode_image_config[0].scratch = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110039726 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
Nigel Taoe360a532021-04-05 22:47:03 +100039727 while (true) {
39728 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39729 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39730 goto suspend;
39731 }
39732 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
Nigel Taobf9dab32021-11-18 19:19:55 +110039733 uint32_t num_bits_0 = ((uint32_t)(*scratch >> 56));
Nigel Taoe360a532021-04-05 22:47:03 +100039734 *scratch <<= 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110039735 *scratch >>= 8;
39736 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_0;
39737 if (num_bits_0 == 56) {
39738 t_0 = ((uint64_t)(*scratch));
Nigel Taoe360a532021-04-05 22:47:03 +100039739 break;
39740 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039741 num_bits_0 += 8;
39742 *scratch |= ((uint64_t)(num_bits_0)) << 56;
Nigel Taoe360a532021-04-05 22:47:03 +100039743 }
39744 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039745 v_magic = t_0;
39746 }
39747 if (v_magic != 727905341920923785) {
39748 status = wuffs_base__make_status(wuffs_png__error__bad_header);
39749 goto exit;
39750 }
39751 {
39752 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
39753 uint64_t t_1;
39754 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 8)) {
39755 t_1 = wuffs_base__peek_u64le__no_bounds_check(iop_a_src);
39756 iop_a_src += 8;
39757 } else {
39758 self->private_data.s_decode_image_config[0].scratch = 0;
39759 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
39760 while (true) {
39761 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39762 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39763 goto suspend;
39764 }
39765 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
39766 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
39767 *scratch <<= 8;
39768 *scratch >>= 8;
39769 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
39770 if (num_bits_1 == 56) {
39771 t_1 = ((uint64_t)(*scratch));
39772 break;
39773 }
39774 num_bits_1 += 8;
39775 *scratch |= ((uint64_t)(num_bits_1)) << 56;
39776 }
39777 }
39778 v_magic = t_1;
39779 }
39780 if (v_magic != 5927942488114331648) {
Nigel Tao123a5c62022-06-03 14:17:20 +100039781 if (v_magic == 5278895250759221248) {
39782 status = wuffs_base__make_status(wuffs_png__error__unsupported_cgbi_extension);
39783 goto exit;
39784 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039785 status = wuffs_base__make_status(wuffs_png__error__bad_header);
39786 goto exit;
39787 }
39788 self->private_impl.f_chunk_type_array[0] = 73;
39789 self->private_impl.f_chunk_type_array[1] = 72;
39790 self->private_impl.f_chunk_type_array[2] = 68;
39791 self->private_impl.f_chunk_type_array[3] = 82;
39792 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
39793 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
39794 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
39795 while (true) {
39796 v_mark = ((uint64_t)(iop_a_src - io0_a_src));
39797 {
39798 if (a_src) {
39799 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39800 }
39801 wuffs_base__status t_2 = wuffs_png__decoder__decode_ihdr(self, a_src);
39802 v_status = t_2;
39803 if (a_src) {
39804 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39805 }
39806 }
39807 if ( ! self->private_impl.f_ignore_checksum) {
39808 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));
39809 }
39810 if (wuffs_base__status__is_ok(&v_status)) {
39811 goto label__0__break;
39812 }
39813 status = v_status;
39814 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
39815 }
39816 label__0__break:;
39817 {
39818 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
39819 uint32_t t_3;
39820 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
39821 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39822 iop_a_src += 4;
39823 } else {
39824 self->private_data.s_decode_image_config[0].scratch = 0;
39825 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
39826 while (true) {
39827 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39828 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39829 goto suspend;
39830 }
39831 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
39832 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
39833 *scratch >>= 8;
39834 *scratch <<= 8;
39835 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
39836 if (num_bits_3 == 24) {
39837 t_3 = ((uint32_t)(*scratch >> 32));
39838 break;
39839 }
39840 num_bits_3 += 8;
39841 *scratch |= ((uint64_t)(num_bits_3));
39842 }
39843 }
39844 v_checksum_want = t_3;
39845 }
39846 if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != v_checksum_want)) {
39847 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
39848 goto exit;
39849 }
Nigel Tao123a5c62022-06-03 14:17:20 +100039850 self->private_impl.f_seen_ihdr = true;
39851 } else if (self->private_impl.f_metadata_fourcc != 0) {
39852 self->private_impl.f_call_sequence = 16;
39853 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
39854 goto ok;
Nigel Taobf9dab32021-11-18 19:19:55 +110039855 }
39856 while (true) {
39857 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
39858 if (a_src && a_src->meta.closed) {
39859 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39860 goto exit;
39861 }
39862 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39863 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
39864 }
39865 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
39866 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
39867 if (self->private_impl.f_chunk_type == 1413563465) {
39868 if ( ! self->private_impl.f_seen_actl || self->private_impl.f_seen_fctl) {
39869 goto label__1__break;
39870 }
39871 self->private_impl.f_seen_idat = true;
39872 } else if (self->private_impl.f_chunk_type == 1413571686) {
39873 if (self->private_impl.f_seen_idat && self->private_impl.f_seen_fctl) {
39874 goto label__1__break;
39875 }
39876 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
39877 goto exit;
39878 }
39879 iop_a_src += 8;
39880 if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32) == 0)) {
39881 self->private_impl.f_chunk_type_array[0] = ((uint8_t)(((self->private_impl.f_chunk_type >> 0) & 255)));
39882 self->private_impl.f_chunk_type_array[1] = ((uint8_t)(((self->private_impl.f_chunk_type >> 8) & 255)));
39883 self->private_impl.f_chunk_type_array[2] = ((uint8_t)(((self->private_impl.f_chunk_type >> 16) & 255)));
39884 self->private_impl.f_chunk_type_array[3] = ((uint8_t)(((self->private_impl.f_chunk_type >> 24) & 255)));
39885 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
39886 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
39887 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
39888 }
39889 while (true) {
39890 v_mark = ((uint64_t)(iop_a_src - io0_a_src));
39891 {
39892 if (a_src) {
39893 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39894 }
Nigel Tao123a5c62022-06-03 14:17:20 +100039895 wuffs_base__status t_4 = wuffs_png__decoder__decode_other_chunk(self, a_src, false);
Nigel Taobf9dab32021-11-18 19:19:55 +110039896 v_status = t_4;
39897 if (a_src) {
39898 iop_a_src = a_src->data.ptr + a_src->meta.ri;
39899 }
39900 }
39901 if ( ! self->private_impl.f_ignore_checksum && ((self->private_impl.f_chunk_type & 32) == 0)) {
39902 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));
39903 }
39904 if (wuffs_base__status__is_ok(&v_status)) {
39905 goto label__2__break;
39906 }
39907 status = v_status;
39908 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
39909 }
39910 label__2__break:;
39911 if (self->private_impl.f_metadata_fourcc != 0) {
Nigel Tao123a5c62022-06-03 14:17:20 +100039912 self->private_impl.f_call_sequence = 16;
Nigel Taobf9dab32021-11-18 19:19:55 +110039913 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
39914 goto ok;
Nigel Taoe360a532021-04-05 22:47:03 +100039915 }
39916 {
39917 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
39918 uint32_t t_5;
39919 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110039920 t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
Nigel Taoe360a532021-04-05 22:47:03 +100039921 iop_a_src += 4;
39922 } else {
39923 self->private_data.s_decode_image_config[0].scratch = 0;
39924 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
39925 while (true) {
39926 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
39927 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
39928 goto suspend;
39929 }
39930 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
Nigel Taobf9dab32021-11-18 19:19:55 +110039931 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
Nigel Taoe360a532021-04-05 22:47:03 +100039932 *scratch >>= 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110039933 *scratch <<= 8;
39934 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
Nigel Taoe360a532021-04-05 22:47:03 +100039935 if (num_bits_5 == 24) {
Nigel Taobf9dab32021-11-18 19:19:55 +110039936 t_5 = ((uint32_t)(*scratch >> 32));
Nigel Taoe360a532021-04-05 22:47:03 +100039937 break;
39938 }
39939 num_bits_5 += 8;
Nigel Taobf9dab32021-11-18 19:19:55 +110039940 *scratch |= ((uint64_t)(num_bits_5));
Nigel Taoe360a532021-04-05 22:47:03 +100039941 }
39942 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039943 v_checksum_want = t_5;
Nigel Taoe360a532021-04-05 22:47:03 +100039944 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039945 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 +100039946 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
39947 goto exit;
39948 }
39949 }
39950 label__1__break:;
39951 if ((self->private_impl.f_color_type == 3) && ! self->private_impl.f_seen_plte) {
39952 status = wuffs_base__make_status(wuffs_png__error__missing_palette);
39953 goto exit;
39954 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100039955 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 +110039956 self->private_impl.f_first_config_io_position = self->private_impl.f_frame_config_io_position;
Nigel Taoe360a532021-04-05 22:47:03 +100039957 if (a_dst != NULL) {
39958 wuffs_base__image_config__set(
39959 a_dst,
39960 self->private_impl.f_dst_pixfmt,
39961 0,
39962 self->private_impl.f_width,
39963 self->private_impl.f_height,
Nigel Taobf9dab32021-11-18 19:19:55 +110039964 self->private_impl.f_first_config_io_position,
Nigel Taoe360a532021-04-05 22:47:03 +100039965 ((self->private_impl.f_color_type <= 3) && ! self->private_impl.f_seen_trns));
39966 }
Nigel Taobf9dab32021-11-18 19:19:55 +110039967 if ( ! self->private_impl.f_seen_actl) {
39968 self->private_impl.f_num_animation_frames_value = 1;
39969 self->private_impl.f_first_rect_x0 = 0;
39970 self->private_impl.f_first_rect_y0 = 0;
39971 self->private_impl.f_first_rect_x1 = self->private_impl.f_width;
39972 self->private_impl.f_first_rect_y1 = self->private_impl.f_height;
39973 self->private_impl.f_first_duration = 0;
39974 self->private_impl.f_first_disposal = 0;
39975 self->private_impl.f_first_overwrite_instead_of_blend = false;
39976 }
Nigel Tao123a5c62022-06-03 14:17:20 +100039977 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100039978
Nigel Taoe360a532021-04-05 22:47:03 +100039979 ok:
39980 self->private_impl.p_decode_image_config[0] = 0;
39981 goto exit;
39982 }
39983
39984 goto suspend;
39985 suspend:
39986 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
39987 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
39988 self->private_data.s_decode_image_config[0].v_checksum_have = v_checksum_have;
39989
39990 goto exit;
39991 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110039992 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100039993 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
39994 }
39995
39996 if (wuffs_base__status__is_error(&status)) {
39997 self->private_impl.magic = WUFFS_BASE__DISABLED;
39998 }
39999 return status;
40000}
40001
40002// -------- func png.decoder.decode_ihdr
40003
40004static wuffs_base__status
40005wuffs_png__decoder__decode_ihdr(
40006 wuffs_png__decoder* self,
40007 wuffs_base__io_buffer* a_src) {
40008 wuffs_base__status status = wuffs_base__make_status(NULL);
40009
40010 uint32_t v_a32 = 0;
40011 uint8_t v_a8 = 0;
40012
40013 const uint8_t* iop_a_src = NULL;
40014 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40015 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40016 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110040017 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100040018 io0_a_src = a_src->data.ptr;
40019 io1_a_src = io0_a_src + a_src->meta.ri;
40020 iop_a_src = io1_a_src;
40021 io2_a_src = io0_a_src + a_src->meta.wi;
40022 }
40023
40024 uint32_t coro_susp_point = self->private_impl.p_decode_ihdr[0];
40025 switch (coro_susp_point) {
40026 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40027
40028 {
40029 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
40030 uint32_t t_0;
40031 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40032 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40033 iop_a_src += 4;
40034 } else {
40035 self->private_data.s_decode_ihdr[0].scratch = 0;
40036 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
40037 while (true) {
40038 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40039 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40040 goto suspend;
40041 }
40042 uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch;
40043 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
40044 *scratch >>= 8;
40045 *scratch <<= 8;
40046 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
40047 if (num_bits_0 == 24) {
40048 t_0 = ((uint32_t)(*scratch >> 32));
40049 break;
40050 }
40051 num_bits_0 += 8;
40052 *scratch |= ((uint64_t)(num_bits_0));
40053 }
40054 }
40055 v_a32 = t_0;
40056 }
Nigel Tao5571bfe2021-06-24 22:44:29 +100040057 if ((v_a32 == 0) || (v_a32 >= 2147483648)) {
Nigel Taoe360a532021-04-05 22:47:03 +100040058 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40059 goto exit;
40060 } else if (v_a32 >= 16777216) {
40061 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
40062 goto exit;
40063 }
40064 self->private_impl.f_width = v_a32;
40065 {
40066 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
40067 uint32_t t_1;
40068 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40069 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40070 iop_a_src += 4;
40071 } else {
40072 self->private_data.s_decode_ihdr[0].scratch = 0;
40073 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
40074 while (true) {
40075 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40076 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40077 goto suspend;
40078 }
40079 uint64_t* scratch = &self->private_data.s_decode_ihdr[0].scratch;
40080 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
40081 *scratch >>= 8;
40082 *scratch <<= 8;
40083 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
40084 if (num_bits_1 == 24) {
40085 t_1 = ((uint32_t)(*scratch >> 32));
40086 break;
40087 }
40088 num_bits_1 += 8;
40089 *scratch |= ((uint64_t)(num_bits_1));
40090 }
40091 }
40092 v_a32 = t_1;
40093 }
Nigel Tao5571bfe2021-06-24 22:44:29 +100040094 if ((v_a32 == 0) || (v_a32 >= 2147483648)) {
Nigel Taoe360a532021-04-05 22:47:03 +100040095 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40096 goto exit;
40097 } else if (v_a32 >= 16777216) {
40098 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
40099 goto exit;
40100 }
40101 self->private_impl.f_height = v_a32;
40102 {
40103 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
40104 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40105 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40106 goto suspend;
40107 }
40108 uint8_t t_2 = *iop_a_src++;
40109 v_a8 = t_2;
40110 }
40111 if (v_a8 > 16) {
40112 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40113 goto exit;
40114 }
40115 self->private_impl.f_depth = v_a8;
40116 {
40117 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
40118 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40119 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40120 goto suspend;
40121 }
40122 uint8_t t_3 = *iop_a_src++;
40123 v_a8 = t_3;
40124 }
40125 if ((v_a8 == 1) || (v_a8 == 5) || (v_a8 > 6)) {
40126 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40127 goto exit;
40128 }
40129 self->private_impl.f_color_type = v_a8;
40130 {
40131 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
40132 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40133 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40134 goto suspend;
40135 }
40136 uint8_t t_4 = *iop_a_src++;
40137 v_a8 = t_4;
40138 }
40139 if (v_a8 != 0) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040140 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
Nigel Taoe360a532021-04-05 22:47:03 +100040141 goto exit;
40142 }
40143 {
40144 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
40145 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40146 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40147 goto suspend;
40148 }
40149 uint8_t t_5 = *iop_a_src++;
40150 v_a8 = t_5;
40151 }
40152 if (v_a8 != 0) {
40153 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40154 goto exit;
40155 }
40156 {
40157 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
40158 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40159 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40160 goto suspend;
40161 }
40162 uint8_t t_6 = *iop_a_src++;
40163 v_a8 = t_6;
40164 }
40165 if (v_a8 == 0) {
40166 self->private_impl.f_interlace_pass = 0;
40167 } else if (v_a8 == 1) {
40168 self->private_impl.f_interlace_pass = 1;
40169 self->private_impl.choosy_filter_and_swizzle = (
40170 &wuffs_png__decoder__filter_and_swizzle_tricky);
40171 } else {
40172 status = wuffs_base__make_status(wuffs_png__error__bad_header);
40173 goto exit;
40174 }
40175 self->private_impl.f_filter_distance = 0;
40176 wuffs_png__decoder__assign_filter_distance(self);
40177 if (self->private_impl.f_filter_distance == 0) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040178 status = wuffs_base__make_status(wuffs_png__error__bad_header);
Nigel Taoe360a532021-04-05 22:47:03 +100040179 goto exit;
40180 }
40181 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)));
40182 wuffs_png__decoder__choose_filter_implementations(self);
40183
40184 goto ok;
40185 ok:
40186 self->private_impl.p_decode_ihdr[0] = 0;
40187 goto exit;
40188 }
40189
40190 goto suspend;
40191 suspend:
40192 self->private_impl.p_decode_ihdr[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
40193
40194 goto exit;
40195 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110040196 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100040197 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40198 }
40199
40200 return status;
40201}
40202
40203// -------- func png.decoder.assign_filter_distance
40204
40205static wuffs_base__empty_struct
40206wuffs_png__decoder__assign_filter_distance(
40207 wuffs_png__decoder* self) {
40208 if (self->private_impl.f_depth < 8) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040209 if ((self->private_impl.f_depth != 1) && (self->private_impl.f_depth != 2) && (self->private_impl.f_depth != 4)) {
40210 return wuffs_base__make_empty_struct();
40211 } else if (self->private_impl.f_color_type == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100040212 self->private_impl.f_dst_pixfmt = 536870920;
40213 self->private_impl.f_src_pixfmt = 536870920;
40214 } else if (self->private_impl.f_color_type == 3) {
40215 self->private_impl.f_dst_pixfmt = 2198077448;
40216 self->private_impl.f_src_pixfmt = 2198077448;
40217 } else {
40218 return wuffs_base__make_empty_struct();
40219 }
40220 self->private_impl.f_filter_distance = 1;
40221 self->private_impl.choosy_filter_and_swizzle = (
40222 &wuffs_png__decoder__filter_and_swizzle_tricky);
40223 } else if (self->private_impl.f_color_type == 0) {
40224 if (self->private_impl.f_depth == 8) {
40225 self->private_impl.f_dst_pixfmt = 536870920;
40226 self->private_impl.f_src_pixfmt = 536870920;
40227 self->private_impl.f_filter_distance = 1;
40228 } else if (self->private_impl.f_depth == 16) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110040229 if (self->private_impl.f_interlace_pass == 0) {
40230 self->private_impl.f_dst_pixfmt = 536870923;
40231 self->private_impl.f_src_pixfmt = 537919499;
40232 } else {
40233 self->private_impl.f_dst_pixfmt = 2164308923;
40234 self->private_impl.f_src_pixfmt = 2164308923;
40235 }
Nigel Taoe360a532021-04-05 22:47:03 +100040236 self->private_impl.f_filter_distance = 2;
40237 }
40238 } else if (self->private_impl.f_color_type == 2) {
40239 if (self->private_impl.f_depth == 8) {
40240 self->private_impl.f_dst_pixfmt = 2147485832;
40241 self->private_impl.f_src_pixfmt = 2684356744;
40242 self->private_impl.f_filter_distance = 3;
40243 } else if (self->private_impl.f_depth == 16) {
40244 self->private_impl.f_dst_pixfmt = 2164308923;
40245 self->private_impl.f_src_pixfmt = 2164308923;
40246 self->private_impl.f_filter_distance = 6;
40247 self->private_impl.choosy_filter_and_swizzle = (
40248 &wuffs_png__decoder__filter_and_swizzle_tricky);
40249 }
40250 } else if (self->private_impl.f_color_type == 3) {
40251 if (self->private_impl.f_depth == 8) {
40252 self->private_impl.f_dst_pixfmt = 2198077448;
40253 self->private_impl.f_src_pixfmt = 2198077448;
40254 self->private_impl.f_filter_distance = 1;
40255 }
40256 } else if (self->private_impl.f_color_type == 4) {
40257 if (self->private_impl.f_depth == 8) {
40258 self->private_impl.f_dst_pixfmt = 2164295816;
40259 self->private_impl.f_src_pixfmt = 2164295816;
40260 self->private_impl.f_filter_distance = 2;
40261 self->private_impl.choosy_filter_and_swizzle = (
40262 &wuffs_png__decoder__filter_and_swizzle_tricky);
40263 } else if (self->private_impl.f_depth == 16) {
40264 self->private_impl.f_dst_pixfmt = 2164308923;
40265 self->private_impl.f_src_pixfmt = 2164308923;
40266 self->private_impl.f_filter_distance = 4;
40267 self->private_impl.choosy_filter_and_swizzle = (
40268 &wuffs_png__decoder__filter_and_swizzle_tricky);
40269 }
40270 } else if (self->private_impl.f_color_type == 6) {
40271 if (self->private_impl.f_depth == 8) {
40272 self->private_impl.f_dst_pixfmt = 2164295816;
40273 self->private_impl.f_src_pixfmt = 2701166728;
40274 self->private_impl.f_filter_distance = 4;
40275 } else if (self->private_impl.f_depth == 16) {
40276 self->private_impl.f_dst_pixfmt = 2164308923;
40277 self->private_impl.f_src_pixfmt = 2164308923;
40278 self->private_impl.f_filter_distance = 8;
40279 self->private_impl.choosy_filter_and_swizzle = (
40280 &wuffs_png__decoder__filter_and_swizzle_tricky);
40281 }
40282 }
40283 return wuffs_base__make_empty_struct();
40284}
40285
40286// -------- func png.decoder.calculate_bytes_per_row
40287
40288static uint64_t
40289wuffs_png__decoder__calculate_bytes_per_row(
40290 const wuffs_png__decoder* self,
40291 uint32_t a_width) {
40292 uint64_t v_bytes_per_channel = 0;
40293
40294 if (self->private_impl.f_depth == 1) {
40295 return ((uint64_t)(((a_width + 7) / 8)));
40296 } else if (self->private_impl.f_depth == 2) {
40297 return ((uint64_t)(((a_width + 3) / 4)));
40298 } else if (self->private_impl.f_depth == 4) {
40299 return ((uint64_t)(((a_width + 1) / 2)));
40300 }
40301 v_bytes_per_channel = ((uint64_t)((self->private_impl.f_depth >> 3)));
40302 return (((uint64_t)(a_width)) * v_bytes_per_channel * ((uint64_t)(WUFFS_PNG__NUM_CHANNELS[self->private_impl.f_color_type])));
40303}
40304
40305// -------- func png.decoder.choose_filter_implementations
40306
40307static wuffs_base__empty_struct
40308wuffs_png__decoder__choose_filter_implementations(
40309 wuffs_png__decoder* self) {
40310 if (self->private_impl.f_filter_distance == 3) {
40311 self->private_impl.choosy_filter_1 = (
40312 &wuffs_png__decoder__filter_1_distance_3_fallback);
40313 self->private_impl.choosy_filter_3 = (
40314 &wuffs_png__decoder__filter_3_distance_3_fallback);
40315 self->private_impl.choosy_filter_4 = (
40316#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
40317 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_3_arm_neon :
40318#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110040319#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100040320 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_3_x86_sse42 :
40321#endif
40322 &wuffs_png__decoder__filter_4_distance_3_fallback);
40323 } else if (self->private_impl.f_filter_distance == 4) {
40324 self->private_impl.choosy_filter_1 = (
40325#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
40326 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_1_distance_4_arm_neon :
40327#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110040328#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100040329 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_1_distance_4_x86_sse42 :
40330#endif
40331 &wuffs_png__decoder__filter_1_distance_4_fallback);
40332 self->private_impl.choosy_filter_3 = (
40333#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
40334 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_3_distance_4_arm_neon :
40335#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110040336#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100040337 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_3_distance_4_x86_sse42 :
40338#endif
40339 &wuffs_png__decoder__filter_3_distance_4_fallback);
40340 self->private_impl.choosy_filter_4 = (
40341#if defined(WUFFS_BASE__CPU_ARCH__ARM_NEON)
40342 wuffs_base__cpu_arch__have_arm_neon() ? &wuffs_png__decoder__filter_4_distance_4_arm_neon :
40343#endif
Nigel Tao7804ffe2021-10-07 21:58:26 +110040344#if defined(WUFFS_BASE__CPU_ARCH__X86_FAMILY)
Nigel Taoe360a532021-04-05 22:47:03 +100040345 wuffs_base__cpu_arch__have_x86_sse42() ? &wuffs_png__decoder__filter_4_distance_4_x86_sse42 :
40346#endif
40347 &wuffs_png__decoder__filter_4_distance_4_fallback);
40348 }
40349 return wuffs_base__make_empty_struct();
40350}
40351
40352// -------- func png.decoder.decode_other_chunk
40353
40354static wuffs_base__status
40355wuffs_png__decoder__decode_other_chunk(
40356 wuffs_png__decoder* self,
Nigel Tao123a5c62022-06-03 14:17:20 +100040357 wuffs_base__io_buffer* a_src,
40358 bool a_framy) {
Nigel Taoe360a532021-04-05 22:47:03 +100040359 wuffs_base__status status = wuffs_base__make_status(NULL);
40360
40361 const uint8_t* iop_a_src = NULL;
40362 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40363 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40364 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110040365 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100040366 io0_a_src = a_src->data.ptr;
40367 io1_a_src = io0_a_src + a_src->meta.ri;
40368 iop_a_src = io1_a_src;
40369 io2_a_src = io0_a_src + a_src->meta.wi;
40370 }
40371
40372 uint32_t coro_susp_point = self->private_impl.p_decode_other_chunk[0];
40373 switch (coro_susp_point) {
40374 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40375
Nigel Tao123a5c62022-06-03 14:17:20 +100040376 if ((self->private_impl.f_chunk_type == 1163152464) && ! a_framy) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110040377 if (self->private_impl.f_seen_plte) {
Nigel Taoe360a532021-04-05 22:47:03 +100040378 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40379 goto exit;
Nigel Taoebbecaa2022-01-08 14:08:27 +110040380 } else if (self->private_impl.f_color_type == 3) {
40381 if (a_src) {
40382 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40383 }
40384 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
40385 status = wuffs_png__decoder__decode_plte(self, a_src);
40386 if (a_src) {
40387 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40388 }
40389 if (status.repr) {
40390 goto suspend;
40391 }
40392 } else if ((self->private_impl.f_color_type == 2) || (self->private_impl.f_color_type == 6)) {
40393 } else {
40394 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40395 goto exit;
Nigel Taoe360a532021-04-05 22:47:03 +100040396 }
40397 self->private_impl.f_seen_plte = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110040398 } else if ((self->private_impl.f_chunk_type & 32) == 0) {
40399 if (self->private_impl.f_chunk_type != 1413563465) {
40400 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40401 goto exit;
40402 }
Nigel Tao123a5c62022-06-03 14:17:20 +100040403 }
40404 if (self->private_impl.f_chunk_type == 1716082789) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110040405 if (self->private_impl.f_report_metadata_exif) {
40406 if (self->private_impl.f_seen_exif) {
40407 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40408 goto exit;
40409 }
40410 if (a_src) {
40411 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40412 }
Nigel Tao123a5c62022-06-03 14:17:20 +100040413 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
Nigel Taoebbecaa2022-01-08 14:08:27 +110040414 status = wuffs_png__decoder__decode_exif(self, a_src);
40415 if (a_src) {
40416 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40417 }
40418 if (status.repr) {
40419 goto suspend;
40420 }
40421 self->private_impl.f_seen_exif = true;
40422 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040423 } else if ((self->private_impl.f_chunk_type == 1951945833) || (self->private_impl.f_chunk_type == 1951942004) || (self->private_impl.f_chunk_type == 1951945850)) {
40424 if (self->private_impl.f_report_metadata_kvp) {
40425 self->private_impl.f_metadata_flavor = 4;
40426 self->private_impl.f_metadata_fourcc = 1263947851;
40427 self->private_impl.f_metadata_x = 0;
40428 self->private_impl.f_metadata_y = 0;
40429 self->private_impl.f_metadata_z = 0;
40430 }
Nigel Tao123a5c62022-06-03 14:17:20 +100040431 } else if ( ! a_framy) {
40432 if (self->private_impl.f_chunk_type == 1280598881) {
40433 if (self->private_impl.f_seen_actl) {
40434 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40435 goto exit;
40436 }
40437 if (a_src) {
40438 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40439 }
40440 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
40441 status = wuffs_png__decoder__decode_actl(self, a_src);
40442 if (a_src) {
40443 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40444 }
40445 if (status.repr) {
40446 goto suspend;
40447 }
40448 self->private_impl.f_seen_actl = true;
40449 } else if (self->private_impl.f_chunk_type == 1297238115) {
40450 if (self->private_impl.f_report_metadata_chrm) {
40451 if (self->private_impl.f_seen_chrm) {
40452 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40453 goto exit;
40454 }
40455 if (a_src) {
40456 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40457 }
40458 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
40459 status = wuffs_png__decoder__decode_chrm(self, a_src);
40460 if (a_src) {
40461 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40462 }
40463 if (status.repr) {
40464 goto suspend;
40465 }
40466 self->private_impl.f_seen_chrm = true;
40467 }
40468 } else if (self->private_impl.f_chunk_type == 1280598886) {
40469 if (self->private_impl.f_seen_fctl) {
40470 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40471 goto exit;
40472 }
40473 if (a_src) {
40474 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40475 }
40476 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
40477 status = wuffs_png__decoder__decode_fctl(self, a_src);
40478 if (a_src) {
40479 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40480 }
40481 if (status.repr) {
40482 goto suspend;
40483 }
40484 self->private_impl.f_seen_fctl = true;
40485 } else if (self->private_impl.f_chunk_type == 1095582055) {
40486 if (self->private_impl.f_report_metadata_gama) {
40487 if (self->private_impl.f_seen_gama) {
40488 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40489 goto exit;
40490 }
40491 if (a_src) {
40492 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40493 }
40494 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
40495 status = wuffs_png__decoder__decode_gama(self, a_src);
40496 if (a_src) {
40497 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40498 }
40499 if (status.repr) {
40500 goto suspend;
40501 }
40502 self->private_impl.f_seen_gama = true;
40503 }
40504 } else if (self->private_impl.f_chunk_type == 1346585449) {
40505 if (self->private_impl.f_report_metadata_iccp) {
40506 if (self->private_impl.f_seen_iccp) {
40507 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40508 goto exit;
40509 }
40510 if (a_src) {
40511 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40512 }
40513 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
40514 status = wuffs_png__decoder__decode_iccp(self, a_src);
40515 if (a_src) {
40516 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40517 }
40518 if (status.repr) {
40519 goto suspend;
40520 }
40521 self->private_impl.f_seen_iccp = true;
40522 }
40523 } else if (self->private_impl.f_chunk_type == 1111970419) {
40524 if (self->private_impl.f_report_metadata_srgb) {
40525 if (self->private_impl.f_seen_srgb) {
40526 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40527 goto exit;
40528 }
40529 if (a_src) {
40530 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40531 }
40532 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
40533 status = wuffs_png__decoder__decode_srgb(self, a_src);
40534 if (a_src) {
40535 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40536 }
40537 if (status.repr) {
40538 goto suspend;
40539 }
40540 self->private_impl.f_seen_srgb = true;
40541 }
40542 } else if (self->private_impl.f_chunk_type == 1397641844) {
40543 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)) {
40544 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40545 goto exit;
40546 }
40547 if (a_src) {
40548 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40549 }
40550 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
40551 status = wuffs_png__decoder__decode_trns(self, a_src);
40552 if (a_src) {
40553 iop_a_src = a_src->data.ptr + a_src->meta.ri;
40554 }
40555 if (status.repr) {
40556 goto suspend;
40557 }
40558 self->private_impl.f_seen_trns = true;
40559 }
Nigel Taobf9dab32021-11-18 19:19:55 +110040560 }
40561 if (self->private_impl.f_metadata_fourcc == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100040562 self->private_data.s_decode_other_chunk[0].scratch = self->private_impl.f_chunk_length;
Nigel Taoebbecaa2022-01-08 14:08:27 +110040563 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
Nigel Taoe360a532021-04-05 22:47:03 +100040564 if (self->private_data.s_decode_other_chunk[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
40565 self->private_data.s_decode_other_chunk[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
40566 iop_a_src = io2_a_src;
40567 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40568 goto suspend;
40569 }
40570 iop_a_src += self->private_data.s_decode_other_chunk[0].scratch;
40571 }
40572
40573 goto ok;
40574 ok:
40575 self->private_impl.p_decode_other_chunk[0] = 0;
40576 goto exit;
40577 }
40578
40579 goto suspend;
40580 suspend:
40581 self->private_impl.p_decode_other_chunk[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
40582
40583 goto exit;
40584 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110040585 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100040586 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40587 }
40588
40589 return status;
40590}
40591
Nigel Taobf9dab32021-11-18 19:19:55 +110040592// -------- func png.decoder.decode_actl
40593
40594static wuffs_base__status
40595wuffs_png__decoder__decode_actl(
40596 wuffs_png__decoder* self,
40597 wuffs_base__io_buffer* a_src) {
40598 wuffs_base__status status = wuffs_base__make_status(NULL);
40599
40600 const uint8_t* iop_a_src = NULL;
40601 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40602 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40603 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110040604 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040605 io0_a_src = a_src->data.ptr;
40606 io1_a_src = io0_a_src + a_src->meta.ri;
40607 iop_a_src = io1_a_src;
40608 io2_a_src = io0_a_src + a_src->meta.wi;
40609 }
40610
40611 uint32_t coro_susp_point = self->private_impl.p_decode_actl[0];
40612 switch (coro_susp_point) {
40613 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40614
40615 if (self->private_impl.f_chunk_length != 8) {
40616 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40617 goto exit;
40618 } else if (self->private_impl.f_interlace_pass > 0) {
40619 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
40620 goto exit;
40621 }
40622 self->private_impl.f_chunk_length = 0;
40623 {
40624 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
40625 uint32_t t_0;
40626 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40627 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40628 iop_a_src += 4;
40629 } else {
40630 self->private_data.s_decode_actl[0].scratch = 0;
40631 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
40632 while (true) {
40633 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40634 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40635 goto suspend;
40636 }
40637 uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch;
40638 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
40639 *scratch >>= 8;
40640 *scratch <<= 8;
40641 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
40642 if (num_bits_0 == 24) {
40643 t_0 = ((uint32_t)(*scratch >> 32));
40644 break;
40645 }
40646 num_bits_0 += 8;
40647 *scratch |= ((uint64_t)(num_bits_0));
40648 }
40649 }
40650 self->private_impl.f_num_animation_frames_value = t_0;
40651 }
40652 if (self->private_impl.f_num_animation_frames_value == 0) {
40653 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40654 goto exit;
40655 }
40656 {
40657 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
40658 uint32_t t_1;
40659 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40660 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
40661 iop_a_src += 4;
40662 } else {
40663 self->private_data.s_decode_actl[0].scratch = 0;
40664 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
40665 while (true) {
40666 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40667 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40668 goto suspend;
40669 }
40670 uint64_t* scratch = &self->private_data.s_decode_actl[0].scratch;
40671 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
40672 *scratch >>= 8;
40673 *scratch <<= 8;
40674 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
40675 if (num_bits_1 == 24) {
40676 t_1 = ((uint32_t)(*scratch >> 32));
40677 break;
40678 }
40679 num_bits_1 += 8;
40680 *scratch |= ((uint64_t)(num_bits_1));
40681 }
40682 }
40683 self->private_impl.f_num_animation_loops_value = t_1;
40684 }
40685
40686 goto ok;
40687 ok:
40688 self->private_impl.p_decode_actl[0] = 0;
40689 goto exit;
40690 }
40691
40692 goto suspend;
40693 suspend:
40694 self->private_impl.p_decode_actl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
40695
40696 goto exit;
40697 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110040698 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040699 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40700 }
40701
40702 return status;
40703}
40704
40705// -------- func png.decoder.decode_chrm
40706
40707static wuffs_base__status
40708wuffs_png__decoder__decode_chrm(
40709 wuffs_png__decoder* self,
40710 wuffs_base__io_buffer* a_src) {
40711 wuffs_base__status status = wuffs_base__make_status(NULL);
40712
40713 uint64_t v_u = 0;
40714
40715 const uint8_t* iop_a_src = NULL;
40716 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40717 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
40718 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110040719 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040720 io0_a_src = a_src->data.ptr;
40721 io1_a_src = io0_a_src + a_src->meta.ri;
40722 iop_a_src = io1_a_src;
40723 io2_a_src = io0_a_src + a_src->meta.wi;
40724 }
40725
40726 uint32_t coro_susp_point = self->private_impl.p_decode_chrm[0];
40727 switch (coro_susp_point) {
40728 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
40729
40730 if (self->private_impl.f_chunk_length != 32) {
40731 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
40732 goto exit;
40733 }
40734 self->private_impl.f_chunk_length = 0;
40735 self->private_impl.f_metadata_flavor = 5;
40736 self->private_impl.f_metadata_fourcc = 1128813133;
40737 self->private_impl.f_metadata_x = 0;
40738 self->private_impl.f_metadata_y = 0;
40739 self->private_impl.f_metadata_z = 0;
40740 {
40741 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
40742 uint64_t t_0;
40743 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40744 t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40745 iop_a_src += 4;
40746 } else {
40747 self->private_data.s_decode_chrm[0].scratch = 0;
40748 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
40749 while (true) {
40750 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40751 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40752 goto suspend;
40753 }
40754 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40755 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
40756 *scratch >>= 8;
40757 *scratch <<= 8;
40758 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
40759 if (num_bits_0 == 24) {
40760 t_0 = ((uint64_t)(*scratch >> 32));
40761 break;
40762 }
40763 num_bits_0 += 8;
40764 *scratch |= ((uint64_t)(num_bits_0));
40765 }
40766 }
40767 v_u = t_0;
40768 }
40769 self->private_impl.f_metadata_x |= ((16777215 & v_u) << 0);
40770 {
40771 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
40772 uint64_t t_1;
40773 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40774 t_1 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40775 iop_a_src += 4;
40776 } else {
40777 self->private_data.s_decode_chrm[0].scratch = 0;
40778 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
40779 while (true) {
40780 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40781 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40782 goto suspend;
40783 }
40784 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40785 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
40786 *scratch >>= 8;
40787 *scratch <<= 8;
40788 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
40789 if (num_bits_1 == 24) {
40790 t_1 = ((uint64_t)(*scratch >> 32));
40791 break;
40792 }
40793 num_bits_1 += 8;
40794 *scratch |= ((uint64_t)(num_bits_1));
40795 }
40796 }
40797 v_u = t_1;
40798 }
40799 self->private_impl.f_metadata_x |= ((16777215 & v_u) << 24);
40800 {
40801 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
40802 uint64_t t_2;
40803 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40804 t_2 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40805 iop_a_src += 4;
40806 } else {
40807 self->private_data.s_decode_chrm[0].scratch = 0;
40808 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
40809 while (true) {
40810 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40811 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40812 goto suspend;
40813 }
40814 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40815 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
40816 *scratch >>= 8;
40817 *scratch <<= 8;
40818 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
40819 if (num_bits_2 == 24) {
40820 t_2 = ((uint64_t)(*scratch >> 32));
40821 break;
40822 }
40823 num_bits_2 += 8;
40824 *scratch |= ((uint64_t)(num_bits_2));
40825 }
40826 }
40827 v_u = t_2;
40828 }
40829 self->private_impl.f_metadata_x |= ((uint64_t)((16777215 & v_u) << 48));
40830 self->private_impl.f_metadata_y |= ((16777215 & v_u) >> 16);
40831 {
40832 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
40833 uint64_t t_3;
40834 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40835 t_3 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40836 iop_a_src += 4;
40837 } else {
40838 self->private_data.s_decode_chrm[0].scratch = 0;
40839 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
40840 while (true) {
40841 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40842 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40843 goto suspend;
40844 }
40845 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40846 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
40847 *scratch >>= 8;
40848 *scratch <<= 8;
40849 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
40850 if (num_bits_3 == 24) {
40851 t_3 = ((uint64_t)(*scratch >> 32));
40852 break;
40853 }
40854 num_bits_3 += 8;
40855 *scratch |= ((uint64_t)(num_bits_3));
40856 }
40857 }
40858 v_u = t_3;
40859 }
40860 self->private_impl.f_metadata_y |= ((16777215 & v_u) << 8);
40861 {
40862 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
40863 uint64_t t_4;
40864 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40865 t_4 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40866 iop_a_src += 4;
40867 } else {
40868 self->private_data.s_decode_chrm[0].scratch = 0;
40869 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
40870 while (true) {
40871 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40872 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40873 goto suspend;
40874 }
40875 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40876 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
40877 *scratch >>= 8;
40878 *scratch <<= 8;
40879 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
40880 if (num_bits_4 == 24) {
40881 t_4 = ((uint64_t)(*scratch >> 32));
40882 break;
40883 }
40884 num_bits_4 += 8;
40885 *scratch |= ((uint64_t)(num_bits_4));
40886 }
40887 }
40888 v_u = t_4;
40889 }
40890 self->private_impl.f_metadata_y |= ((16777215 & v_u) << 32);
40891 {
40892 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
40893 uint64_t t_5;
40894 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40895 t_5 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40896 iop_a_src += 4;
40897 } else {
40898 self->private_data.s_decode_chrm[0].scratch = 0;
40899 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
40900 while (true) {
40901 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40902 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40903 goto suspend;
40904 }
40905 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40906 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
40907 *scratch >>= 8;
40908 *scratch <<= 8;
40909 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
40910 if (num_bits_5 == 24) {
40911 t_5 = ((uint64_t)(*scratch >> 32));
40912 break;
40913 }
40914 num_bits_5 += 8;
40915 *scratch |= ((uint64_t)(num_bits_5));
40916 }
40917 }
40918 v_u = t_5;
40919 }
40920 self->private_impl.f_metadata_y |= ((uint64_t)((16777215 & v_u) << 56));
40921 self->private_impl.f_metadata_z |= ((16777215 & v_u) >> 8);
40922 {
40923 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
40924 uint64_t t_6;
40925 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40926 t_6 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40927 iop_a_src += 4;
40928 } else {
40929 self->private_data.s_decode_chrm[0].scratch = 0;
40930 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
40931 while (true) {
40932 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40933 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40934 goto suspend;
40935 }
40936 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40937 uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFF));
40938 *scratch >>= 8;
40939 *scratch <<= 8;
40940 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6);
40941 if (num_bits_6 == 24) {
40942 t_6 = ((uint64_t)(*scratch >> 32));
40943 break;
40944 }
40945 num_bits_6 += 8;
40946 *scratch |= ((uint64_t)(num_bits_6));
40947 }
40948 }
40949 v_u = t_6;
40950 }
40951 self->private_impl.f_metadata_z |= ((16777215 & v_u) << 16);
40952 {
40953 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
40954 uint64_t t_7;
40955 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
40956 t_7 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
40957 iop_a_src += 4;
40958 } else {
40959 self->private_data.s_decode_chrm[0].scratch = 0;
40960 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
40961 while (true) {
40962 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
40963 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
40964 goto suspend;
40965 }
40966 uint64_t* scratch = &self->private_data.s_decode_chrm[0].scratch;
40967 uint32_t num_bits_7 = ((uint32_t)(*scratch & 0xFF));
40968 *scratch >>= 8;
40969 *scratch <<= 8;
40970 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_7);
40971 if (num_bits_7 == 24) {
40972 t_7 = ((uint64_t)(*scratch >> 32));
40973 break;
40974 }
40975 num_bits_7 += 8;
40976 *scratch |= ((uint64_t)(num_bits_7));
40977 }
40978 }
40979 v_u = t_7;
40980 }
40981 self->private_impl.f_metadata_z |= ((16777215 & v_u) << 40);
40982
40983 goto ok;
40984 ok:
40985 self->private_impl.p_decode_chrm[0] = 0;
40986 goto exit;
40987 }
40988
40989 goto suspend;
40990 suspend:
40991 self->private_impl.p_decode_chrm[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
40992
40993 goto exit;
40994 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110040995 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110040996 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
40997 }
40998
40999 return status;
41000}
41001
Nigel Taoebbecaa2022-01-08 14:08:27 +110041002// -------- func png.decoder.decode_exif
41003
41004static wuffs_base__status
41005wuffs_png__decoder__decode_exif(
41006 wuffs_png__decoder* self,
41007 wuffs_base__io_buffer* a_src) {
41008 wuffs_base__status status = wuffs_base__make_status(NULL);
41009
41010 const uint8_t* iop_a_src = NULL;
41011 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41012 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41013 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041014 if (a_src && a_src->data.ptr) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110041015 io0_a_src = a_src->data.ptr;
41016 io1_a_src = io0_a_src + a_src->meta.ri;
41017 iop_a_src = io1_a_src;
41018 io2_a_src = io0_a_src + a_src->meta.wi;
41019 }
41020
41021 if (self->private_impl.f_chunk_length < 4) {
41022 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41023 goto exit;
41024 }
41025 self->private_impl.f_metadata_flavor = 3;
41026 self->private_impl.f_metadata_fourcc = 1163413830;
41027 self->private_impl.f_metadata_x = 0;
41028 self->private_impl.f_metadata_y = wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src)));
41029 self->private_impl.f_metadata_z = wuffs_base__u64__sat_add(self->private_impl.f_metadata_y, ((uint64_t)(self->private_impl.f_chunk_length)));
41030 self->private_impl.f_chunk_length = 0;
41031
41032 goto ok;
41033 ok:
41034 goto exit;
41035 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041036 if (a_src && a_src->data.ptr) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110041037 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41038 }
41039
41040 return status;
41041}
41042
Nigel Taobf9dab32021-11-18 19:19:55 +110041043// -------- func png.decoder.decode_fctl
41044
41045static wuffs_base__status
41046wuffs_png__decoder__decode_fctl(
41047 wuffs_png__decoder* self,
41048 wuffs_base__io_buffer* a_src) {
41049 wuffs_base__status status = wuffs_base__make_status(NULL);
41050
41051 uint32_t v_x0 = 0;
41052 uint32_t v_y0 = 0;
41053 uint32_t v_x1 = 0;
41054 uint32_t v_y1 = 0;
41055
41056 const uint8_t* iop_a_src = NULL;
41057 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41058 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41059 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041060 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041061 io0_a_src = a_src->data.ptr;
41062 io1_a_src = io0_a_src + a_src->meta.ri;
41063 iop_a_src = io1_a_src;
41064 io2_a_src = io0_a_src + a_src->meta.wi;
41065 }
41066
41067 uint32_t coro_susp_point = self->private_impl.p_decode_fctl[0];
41068 if (coro_susp_point) {
41069 v_x0 = self->private_data.s_decode_fctl[0].v_x0;
41070 v_x1 = self->private_data.s_decode_fctl[0].v_x1;
41071 v_y1 = self->private_data.s_decode_fctl[0].v_y1;
41072 }
41073 switch (coro_susp_point) {
41074 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41075
41076 if (self->private_impl.f_chunk_length != 26) {
41077 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41078 goto exit;
41079 }
41080 self->private_impl.f_chunk_length = 0;
41081 {
41082 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41083 uint32_t t_0;
41084 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41085 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
41086 iop_a_src += 4;
41087 } else {
41088 self->private_data.s_decode_fctl[0].scratch = 0;
41089 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41090 while (true) {
41091 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41092 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41093 goto suspend;
41094 }
41095 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41096 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
41097 *scratch >>= 8;
41098 *scratch <<= 8;
41099 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
41100 if (num_bits_0 == 24) {
41101 t_0 = ((uint32_t)(*scratch >> 32));
41102 break;
41103 }
41104 num_bits_0 += 8;
41105 *scratch |= ((uint64_t)(num_bits_0));
41106 }
41107 }
41108 v_x0 = t_0;
41109 }
41110 if (v_x0 != self->private_impl.f_next_animation_seq_num) {
41111 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
41112 goto exit;
41113 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
41114 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
41115 goto exit;
41116 }
41117 self->private_impl.f_next_animation_seq_num += 1;
41118 {
41119 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
41120 uint32_t t_1;
41121 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41122 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
41123 iop_a_src += 4;
41124 } else {
41125 self->private_data.s_decode_fctl[0].scratch = 0;
41126 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
41127 while (true) {
41128 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41129 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41130 goto suspend;
41131 }
41132 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41133 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
41134 *scratch >>= 8;
41135 *scratch <<= 8;
41136 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
41137 if (num_bits_1 == 24) {
41138 t_1 = ((uint32_t)(*scratch >> 32));
41139 break;
41140 }
41141 num_bits_1 += 8;
41142 *scratch |= ((uint64_t)(num_bits_1));
41143 }
41144 }
41145 v_x1 = t_1;
41146 }
41147 {
41148 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
41149 uint32_t t_2;
41150 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41151 t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
41152 iop_a_src += 4;
41153 } else {
41154 self->private_data.s_decode_fctl[0].scratch = 0;
41155 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
41156 while (true) {
41157 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41158 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41159 goto suspend;
41160 }
41161 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41162 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
41163 *scratch >>= 8;
41164 *scratch <<= 8;
41165 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
41166 if (num_bits_2 == 24) {
41167 t_2 = ((uint32_t)(*scratch >> 32));
41168 break;
41169 }
41170 num_bits_2 += 8;
41171 *scratch |= ((uint64_t)(num_bits_2));
41172 }
41173 }
41174 v_y1 = t_2;
41175 }
41176 {
41177 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
41178 uint32_t t_3;
41179 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41180 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
41181 iop_a_src += 4;
41182 } else {
41183 self->private_data.s_decode_fctl[0].scratch = 0;
41184 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
41185 while (true) {
41186 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41187 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41188 goto suspend;
41189 }
41190 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41191 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
41192 *scratch >>= 8;
41193 *scratch <<= 8;
41194 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
41195 if (num_bits_3 == 24) {
41196 t_3 = ((uint32_t)(*scratch >> 32));
41197 break;
41198 }
41199 num_bits_3 += 8;
41200 *scratch |= ((uint64_t)(num_bits_3));
41201 }
41202 }
41203 v_x0 = t_3;
41204 }
41205 {
41206 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
41207 uint32_t t_4;
41208 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41209 t_4 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
41210 iop_a_src += 4;
41211 } else {
41212 self->private_data.s_decode_fctl[0].scratch = 0;
41213 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
41214 while (true) {
41215 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41216 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41217 goto suspend;
41218 }
41219 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41220 uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
41221 *scratch >>= 8;
41222 *scratch <<= 8;
41223 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
41224 if (num_bits_4 == 24) {
41225 t_4 = ((uint32_t)(*scratch >> 32));
41226 break;
41227 }
41228 num_bits_4 += 8;
41229 *scratch |= ((uint64_t)(num_bits_4));
41230 }
41231 }
41232 v_y0 = t_4;
41233 }
41234 v_x1 += v_x0;
41235 v_y1 += v_y0;
41236 if ((v_x0 >= v_x1) ||
41237 (v_x0 > self->private_impl.f_width) ||
41238 (v_x1 > self->private_impl.f_width) ||
41239 (v_y0 >= v_y1) ||
41240 (v_y0 > self->private_impl.f_height) ||
41241 (v_y1 > self->private_impl.f_height)) {
41242 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41243 goto exit;
41244 }
41245 self->private_impl.f_frame_rect_x0 = v_x0;
41246 self->private_impl.f_frame_rect_y0 = v_y0;
41247 self->private_impl.f_frame_rect_x1 = v_x1;
41248 self->private_impl.f_frame_rect_y1 = v_y1;
41249 {
41250 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
41251 uint32_t t_5;
41252 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
41253 t_5 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
41254 iop_a_src += 2;
41255 } else {
41256 self->private_data.s_decode_fctl[0].scratch = 0;
41257 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
41258 while (true) {
41259 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41260 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41261 goto suspend;
41262 }
41263 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41264 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
41265 *scratch >>= 8;
41266 *scratch <<= 8;
41267 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
41268 if (num_bits_5 == 8) {
41269 t_5 = ((uint32_t)(*scratch >> 48));
41270 break;
41271 }
41272 num_bits_5 += 8;
41273 *scratch |= ((uint64_t)(num_bits_5));
41274 }
41275 }
41276 v_x0 = t_5;
41277 }
41278 {
41279 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
41280 uint32_t t_6;
41281 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
41282 t_6 = ((uint32_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
41283 iop_a_src += 2;
41284 } else {
41285 self->private_data.s_decode_fctl[0].scratch = 0;
41286 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
41287 while (true) {
41288 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41289 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41290 goto suspend;
41291 }
41292 uint64_t* scratch = &self->private_data.s_decode_fctl[0].scratch;
41293 uint32_t num_bits_6 = ((uint32_t)(*scratch & 0xFF));
41294 *scratch >>= 8;
41295 *scratch <<= 8;
41296 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_6);
41297 if (num_bits_6 == 8) {
41298 t_6 = ((uint32_t)(*scratch >> 48));
41299 break;
41300 }
41301 num_bits_6 += 8;
41302 *scratch |= ((uint64_t)(num_bits_6));
41303 }
41304 }
41305 v_x1 = t_6;
41306 }
41307 if (v_x1 <= 0) {
41308 self->private_impl.f_frame_duration = (((uint64_t)(v_x0)) * 7056000);
41309 } else {
41310 self->private_impl.f_frame_duration = ((((uint64_t)(v_x0)) * 705600000) / ((uint64_t)(v_x1)));
41311 }
41312 {
41313 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
41314 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41315 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41316 goto suspend;
41317 }
41318 uint32_t t_7 = *iop_a_src++;
41319 v_x0 = t_7;
41320 }
41321 if (v_x0 == 0) {
41322 self->private_impl.f_frame_disposal = 0;
41323 } else if (v_x0 == 1) {
41324 self->private_impl.f_frame_disposal = 1;
41325 } else if (v_x0 == 2) {
41326 self->private_impl.f_frame_disposal = 2;
41327 } else {
41328 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41329 goto exit;
41330 }
41331 {
41332 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
41333 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41334 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41335 goto suspend;
41336 }
41337 uint32_t t_8 = *iop_a_src++;
41338 v_x0 = t_8;
41339 }
41340 if (v_x0 == 0) {
41341 self->private_impl.f_frame_overwrite_instead_of_blend = true;
41342 } else if (v_x0 == 1) {
41343 self->private_impl.f_frame_overwrite_instead_of_blend = false;
41344 } else {
41345 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41346 goto exit;
41347 }
41348 if (self->private_impl.f_num_decoded_frame_configs_value == 0) {
41349 self->private_impl.f_first_rect_x0 = self->private_impl.f_frame_rect_x0;
41350 self->private_impl.f_first_rect_y0 = self->private_impl.f_frame_rect_y0;
41351 self->private_impl.f_first_rect_x1 = self->private_impl.f_frame_rect_x1;
41352 self->private_impl.f_first_rect_y1 = self->private_impl.f_frame_rect_y1;
41353 self->private_impl.f_first_duration = self->private_impl.f_frame_duration;
41354 self->private_impl.f_first_disposal = self->private_impl.f_frame_disposal;
41355 self->private_impl.f_first_overwrite_instead_of_blend = self->private_impl.f_frame_overwrite_instead_of_blend;
41356 }
41357
41358 goto ok;
41359 ok:
41360 self->private_impl.p_decode_fctl[0] = 0;
41361 goto exit;
41362 }
41363
41364 goto suspend;
41365 suspend:
41366 self->private_impl.p_decode_fctl[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41367 self->private_data.s_decode_fctl[0].v_x0 = v_x0;
41368 self->private_data.s_decode_fctl[0].v_x1 = v_x1;
41369 self->private_data.s_decode_fctl[0].v_y1 = v_y1;
41370
41371 goto exit;
41372 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041373 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041374 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41375 }
41376
41377 return status;
41378}
41379
41380// -------- func png.decoder.decode_gama
41381
41382static wuffs_base__status
41383wuffs_png__decoder__decode_gama(
41384 wuffs_png__decoder* self,
41385 wuffs_base__io_buffer* a_src) {
41386 wuffs_base__status status = wuffs_base__make_status(NULL);
41387
41388 const uint8_t* iop_a_src = NULL;
41389 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41390 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41391 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041392 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041393 io0_a_src = a_src->data.ptr;
41394 io1_a_src = io0_a_src + a_src->meta.ri;
41395 iop_a_src = io1_a_src;
41396 io2_a_src = io0_a_src + a_src->meta.wi;
41397 }
41398
41399 uint32_t coro_susp_point = self->private_impl.p_decode_gama[0];
41400 switch (coro_susp_point) {
41401 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41402
41403 if (self->private_impl.f_chunk_length != 4) {
41404 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41405 goto exit;
41406 }
41407 self->private_impl.f_chunk_length = 0;
41408 self->private_impl.f_metadata_flavor = 5;
41409 self->private_impl.f_metadata_fourcc = 1195461953;
41410 {
41411 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41412 uint64_t t_0;
41413 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
41414 t_0 = ((uint64_t)(wuffs_base__peek_u32be__no_bounds_check(iop_a_src)));
41415 iop_a_src += 4;
41416 } else {
41417 self->private_data.s_decode_gama[0].scratch = 0;
41418 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41419 while (true) {
41420 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41421 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41422 goto suspend;
41423 }
41424 uint64_t* scratch = &self->private_data.s_decode_gama[0].scratch;
41425 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
41426 *scratch >>= 8;
41427 *scratch <<= 8;
41428 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
41429 if (num_bits_0 == 24) {
41430 t_0 = ((uint64_t)(*scratch >> 32));
41431 break;
41432 }
41433 num_bits_0 += 8;
41434 *scratch |= ((uint64_t)(num_bits_0));
41435 }
41436 }
41437 self->private_impl.f_metadata_x = t_0;
41438 }
41439 self->private_impl.f_metadata_y = 0;
41440 self->private_impl.f_metadata_z = 0;
41441
41442 goto ok;
41443 ok:
41444 self->private_impl.p_decode_gama[0] = 0;
41445 goto exit;
41446 }
41447
41448 goto suspend;
41449 suspend:
41450 self->private_impl.p_decode_gama[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41451
41452 goto exit;
41453 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041454 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041455 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41456 }
41457
41458 return status;
41459}
41460
41461// -------- func png.decoder.decode_iccp
41462
41463static wuffs_base__status
41464wuffs_png__decoder__decode_iccp(
41465 wuffs_png__decoder* self,
41466 wuffs_base__io_buffer* a_src) {
41467 wuffs_base__status status = wuffs_base__make_status(NULL);
41468
41469 uint8_t v_c = 0;
41470
41471 const uint8_t* iop_a_src = NULL;
41472 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41473 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41474 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041475 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041476 io0_a_src = a_src->data.ptr;
41477 io1_a_src = io0_a_src + a_src->meta.ri;
41478 iop_a_src = io1_a_src;
41479 io2_a_src = io0_a_src + a_src->meta.wi;
41480 }
41481
41482 uint32_t coro_susp_point = self->private_impl.p_decode_iccp[0];
41483 switch (coro_susp_point) {
41484 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41485
41486 while (true) {
41487 if (self->private_impl.f_chunk_length <= 0) {
41488 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41489 goto exit;
41490 }
41491 self->private_impl.f_chunk_length -= 1;
41492 {
41493 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41494 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41495 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41496 goto suspend;
41497 }
41498 uint8_t t_0 = *iop_a_src++;
41499 v_c = t_0;
41500 }
41501 if (v_c == 0) {
41502 goto label__0__break;
41503 }
41504 }
41505 label__0__break:;
41506 if (self->private_impl.f_chunk_length <= 0) {
41507 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41508 goto exit;
41509 }
41510 self->private_impl.f_chunk_length -= 1;
41511 {
41512 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41513 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41514 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41515 goto suspend;
41516 }
41517 uint8_t t_1 = *iop_a_src++;
41518 v_c = t_1;
41519 }
41520 if (v_c != 0) {
41521 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
41522 goto exit;
41523 }
41524 self->private_impl.f_metadata_is_zlib_compressed = true;
41525 self->private_impl.f_metadata_flavor = 4;
41526 self->private_impl.f_metadata_fourcc = 1229144912;
41527 self->private_impl.f_metadata_x = 0;
41528 self->private_impl.f_metadata_y = 0;
41529 self->private_impl.f_metadata_z = 0;
41530
41531 goto ok;
41532 ok:
41533 self->private_impl.p_decode_iccp[0] = 0;
41534 goto exit;
41535 }
41536
41537 goto suspend;
41538 suspend:
41539 self->private_impl.p_decode_iccp[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41540
41541 goto exit;
41542 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041543 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041544 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41545 }
41546
41547 return status;
41548}
41549
Nigel Taoe360a532021-04-05 22:47:03 +100041550// -------- func png.decoder.decode_plte
41551
41552static wuffs_base__status
41553wuffs_png__decoder__decode_plte(
41554 wuffs_png__decoder* self,
41555 wuffs_base__io_buffer* a_src) {
41556 wuffs_base__status status = wuffs_base__make_status(NULL);
41557
41558 uint32_t v_num_entries = 0;
41559 uint32_t v_i = 0;
41560 uint32_t v_argb = 0;
41561
41562 const uint8_t* iop_a_src = NULL;
41563 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41564 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41565 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041566 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100041567 io0_a_src = a_src->data.ptr;
41568 io1_a_src = io0_a_src + a_src->meta.ri;
41569 iop_a_src = io1_a_src;
41570 io2_a_src = io0_a_src + a_src->meta.wi;
41571 }
41572
41573 uint32_t coro_susp_point = self->private_impl.p_decode_plte[0];
41574 if (coro_susp_point) {
41575 v_num_entries = self->private_data.s_decode_plte[0].v_num_entries;
41576 v_i = self->private_data.s_decode_plte[0].v_i;
41577 }
41578 switch (coro_susp_point) {
41579 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41580
41581 if ((self->private_impl.f_chunk_length > 768) || ((self->private_impl.f_chunk_length % 3) != 0)) {
41582 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41583 goto exit;
41584 }
41585 v_num_entries = (((uint32_t)(self->private_impl.f_chunk_length)) / 3);
Nigel Taobf9dab32021-11-18 19:19:55 +110041586 self->private_impl.f_chunk_length = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100041587 while (v_i < v_num_entries) {
41588 {
41589 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41590 uint32_t t_0;
41591 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
41592 t_0 = ((uint32_t)(wuffs_base__peek_u24be__no_bounds_check(iop_a_src)));
41593 iop_a_src += 3;
41594 } else {
41595 self->private_data.s_decode_plte[0].scratch = 0;
41596 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41597 while (true) {
41598 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41599 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41600 goto suspend;
41601 }
41602 uint64_t* scratch = &self->private_data.s_decode_plte[0].scratch;
41603 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
41604 *scratch >>= 8;
41605 *scratch <<= 8;
41606 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
41607 if (num_bits_0 == 16) {
41608 t_0 = ((uint32_t)(*scratch >> 40));
41609 break;
41610 }
41611 num_bits_0 += 8;
41612 *scratch |= ((uint64_t)(num_bits_0));
41613 }
41614 }
41615 v_argb = t_0;
41616 }
41617 v_argb |= 4278190080;
41618 self->private_data.f_src_palette[((4 * v_i) + 0)] = ((uint8_t)(((v_argb >> 0) & 255)));
41619 self->private_data.f_src_palette[((4 * v_i) + 1)] = ((uint8_t)(((v_argb >> 8) & 255)));
41620 self->private_data.f_src_palette[((4 * v_i) + 2)] = ((uint8_t)(((v_argb >> 16) & 255)));
41621 self->private_data.f_src_palette[((4 * v_i) + 3)] = ((uint8_t)(((v_argb >> 24) & 255)));
41622 v_i += 1;
41623 }
41624 while (v_i < 256) {
41625 self->private_data.f_src_palette[((4 * v_i) + 0)] = 0;
41626 self->private_data.f_src_palette[((4 * v_i) + 1)] = 0;
41627 self->private_data.f_src_palette[((4 * v_i) + 2)] = 0;
41628 self->private_data.f_src_palette[((4 * v_i) + 3)] = 255;
41629 v_i += 1;
41630 }
41631
41632 goto ok;
41633 ok:
41634 self->private_impl.p_decode_plte[0] = 0;
41635 goto exit;
41636 }
41637
41638 goto suspend;
41639 suspend:
41640 self->private_impl.p_decode_plte[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41641 self->private_data.s_decode_plte[0].v_num_entries = v_num_entries;
41642 self->private_data.s_decode_plte[0].v_i = v_i;
41643
41644 goto exit;
41645 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041646 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100041647 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41648 }
41649
41650 return status;
41651}
41652
Nigel Taobf9dab32021-11-18 19:19:55 +110041653// -------- func png.decoder.decode_srgb
41654
41655static wuffs_base__status
41656wuffs_png__decoder__decode_srgb(
41657 wuffs_png__decoder* self,
41658 wuffs_base__io_buffer* a_src) {
41659 wuffs_base__status status = wuffs_base__make_status(NULL);
41660
41661 const uint8_t* iop_a_src = NULL;
41662 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41663 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41664 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041665 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041666 io0_a_src = a_src->data.ptr;
41667 io1_a_src = io0_a_src + a_src->meta.ri;
41668 iop_a_src = io1_a_src;
41669 io2_a_src = io0_a_src + a_src->meta.wi;
41670 }
41671
41672 uint32_t coro_susp_point = self->private_impl.p_decode_srgb[0];
41673 switch (coro_susp_point) {
41674 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41675
41676 if (self->private_impl.f_chunk_length != 1) {
41677 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41678 goto exit;
41679 }
41680 self->private_impl.f_chunk_length = 0;
41681 self->private_impl.f_metadata_flavor = 5;
41682 self->private_impl.f_metadata_fourcc = 1397901122;
41683 {
41684 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41685 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41686 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41687 goto suspend;
41688 }
41689 uint64_t t_0 = *iop_a_src++;
41690 self->private_impl.f_metadata_x = t_0;
41691 }
41692 self->private_impl.f_metadata_y = 0;
41693 self->private_impl.f_metadata_z = 0;
41694
41695 goto ok;
41696 ok:
41697 self->private_impl.p_decode_srgb[0] = 0;
41698 goto exit;
41699 }
41700
41701 goto suspend;
41702 suspend:
41703 self->private_impl.p_decode_srgb[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
41704
41705 goto exit;
41706 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041707 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041708 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41709 }
41710
41711 return status;
41712}
41713
Nigel Taoe360a532021-04-05 22:47:03 +100041714// -------- func png.decoder.decode_trns
41715
41716static wuffs_base__status
41717wuffs_png__decoder__decode_trns(
41718 wuffs_png__decoder* self,
41719 wuffs_base__io_buffer* a_src) {
41720 wuffs_base__status status = wuffs_base__make_status(NULL);
41721
Nigel Taoe360a532021-04-05 22:47:03 +100041722 uint32_t v_i = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110041723 uint32_t v_n = 0;
41724 uint64_t v_u = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100041725
41726 const uint8_t* iop_a_src = NULL;
41727 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41728 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41729 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041730 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100041731 io0_a_src = a_src->data.ptr;
41732 io1_a_src = io0_a_src + a_src->meta.ri;
41733 iop_a_src = io1_a_src;
41734 io2_a_src = io0_a_src + a_src->meta.wi;
41735 }
41736
41737 uint32_t coro_susp_point = self->private_impl.p_decode_trns[0];
41738 if (coro_susp_point) {
Nigel Taoe360a532021-04-05 22:47:03 +100041739 v_i = self->private_data.s_decode_trns[0].v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +110041740 v_n = self->private_data.s_decode_trns[0].v_n;
Nigel Taoe360a532021-04-05 22:47:03 +100041741 }
41742 switch (coro_susp_point) {
41743 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41744
Nigel Taobf9dab32021-11-18 19:19:55 +110041745 if (self->private_impl.f_color_type == 0) {
Nigel Taoe360a532021-04-05 22:47:03 +100041746 self->private_impl.choosy_filter_and_swizzle = (
41747 &wuffs_png__decoder__filter_and_swizzle_tricky);
Nigel Taobf9dab32021-11-18 19:19:55 +110041748 if (self->private_impl.f_depth <= 8) {
Nigel Taoe360a532021-04-05 22:47:03 +100041749 self->private_impl.f_dst_pixfmt = 2164295816;
Nigel Taobf9dab32021-11-18 19:19:55 +110041750 self->private_impl.f_src_pixfmt = 2164295816;
41751 } else {
41752 self->private_impl.f_dst_pixfmt = 2164308923;
Nigel Taoe360a532021-04-05 22:47:03 +100041753 self->private_impl.f_src_pixfmt = 2164308923;
41754 }
Nigel Taobf9dab32021-11-18 19:19:55 +110041755 if (self->private_impl.f_chunk_length != 2) {
41756 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41757 goto exit;
41758 }
41759 self->private_impl.f_chunk_length = 0;
41760 {
41761 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41762 uint64_t t_0;
41763 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
41764 t_0 = ((uint64_t)(wuffs_base__peek_u16be__no_bounds_check(iop_a_src)));
41765 iop_a_src += 2;
41766 } else {
41767 self->private_data.s_decode_trns[0].scratch = 0;
41768 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41769 while (true) {
41770 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41771 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41772 goto suspend;
41773 }
41774 uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch;
41775 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
41776 *scratch >>= 8;
41777 *scratch <<= 8;
41778 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
41779 if (num_bits_0 == 8) {
41780 t_0 = ((uint64_t)(*scratch >> 48));
41781 break;
41782 }
41783 num_bits_0 += 8;
41784 *scratch |= ((uint64_t)(num_bits_0));
41785 }
41786 }
41787 v_u = t_0;
41788 }
41789 if (self->private_impl.f_depth <= 1) {
41790 self->private_impl.f_remap_transparency = (((v_u & 1) * 16777215) | 4278190080);
41791 } else if (self->private_impl.f_depth <= 2) {
41792 self->private_impl.f_remap_transparency = (((v_u & 3) * 5592405) | 4278190080);
41793 } else if (self->private_impl.f_depth <= 4) {
41794 self->private_impl.f_remap_transparency = (((v_u & 15) * 1118481) | 4278190080);
41795 } else if (self->private_impl.f_depth <= 8) {
41796 self->private_impl.f_remap_transparency = (((v_u & 255) * 65793) | 4278190080);
41797 } else {
41798 self->private_impl.f_remap_transparency = ((v_u * 4295032833) | 18446462598732840960u);
41799 }
41800 } else if (self->private_impl.f_color_type == 2) {
41801 self->private_impl.choosy_filter_and_swizzle = (
41802 &wuffs_png__decoder__filter_and_swizzle_tricky);
41803 if (self->private_impl.f_depth <= 8) {
41804 self->private_impl.f_dst_pixfmt = 2164295816;
41805 self->private_impl.f_src_pixfmt = 2164295816;
41806 } else {
41807 self->private_impl.f_dst_pixfmt = 2164308923;
41808 self->private_impl.f_src_pixfmt = 2164308923;
41809 }
41810 if (self->private_impl.f_chunk_length != 6) {
41811 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41812 goto exit;
41813 }
41814 self->private_impl.f_chunk_length = 0;
41815 {
41816 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
41817 uint64_t t_1;
41818 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 6)) {
41819 t_1 = ((uint64_t)(wuffs_base__peek_u48be__no_bounds_check(iop_a_src)));
41820 iop_a_src += 6;
41821 } else {
41822 self->private_data.s_decode_trns[0].scratch = 0;
41823 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
41824 while (true) {
41825 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41826 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41827 goto suspend;
41828 }
41829 uint64_t* scratch = &self->private_data.s_decode_trns[0].scratch;
41830 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
41831 *scratch >>= 8;
41832 *scratch <<= 8;
41833 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
41834 if (num_bits_1 == 40) {
41835 t_1 = ((uint64_t)(*scratch >> 16));
41836 break;
41837 }
41838 num_bits_1 += 8;
41839 *scratch |= ((uint64_t)(num_bits_1));
41840 }
41841 }
41842 v_u = t_1;
41843 }
41844 if (self->private_impl.f_depth <= 8) {
41845 self->private_impl.f_remap_transparency = ((255 & (v_u >> 0)) |
41846 (65280 & (v_u >> 8)) |
41847 (16711680 & (v_u >> 16)) |
41848 4278190080);
41849 } else {
41850 self->private_impl.f_remap_transparency = (v_u | 18446462598732840960u);
41851 }
41852 } else if (self->private_impl.f_color_type == 3) {
41853 self->private_impl.f_dst_pixfmt = 2164523016;
41854 self->private_impl.f_src_pixfmt = 2164523016;
41855 if (self->private_impl.f_chunk_length > 256) {
41856 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41857 goto exit;
41858 }
41859 v_n = ((uint32_t)(self->private_impl.f_chunk_length));
41860 self->private_impl.f_chunk_length = 0;
41861 while (v_i < v_n) {
41862 {
41863 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
41864 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
41865 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
41866 goto suspend;
41867 }
41868 uint8_t t_2 = *iop_a_src++;
41869 self->private_data.f_src_palette[((4 * v_i) + 3)] = t_2;
41870 }
41871 v_i += 1;
41872 }
41873 } else {
41874 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
41875 goto exit;
Nigel Taoe360a532021-04-05 22:47:03 +100041876 }
41877
41878 goto ok;
41879 ok:
41880 self->private_impl.p_decode_trns[0] = 0;
41881 goto exit;
41882 }
41883
41884 goto suspend;
41885 suspend:
41886 self->private_impl.p_decode_trns[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100041887 self->private_data.s_decode_trns[0].v_i = v_i;
Nigel Taobf9dab32021-11-18 19:19:55 +110041888 self->private_data.s_decode_trns[0].v_n = v_n;
Nigel Taoe360a532021-04-05 22:47:03 +100041889
41890 goto exit;
41891 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110041892 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100041893 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41894 }
41895
41896 return status;
41897}
41898
41899// -------- func png.decoder.decode_frame_config
41900
41901WUFFS_BASE__MAYBE_STATIC wuffs_base__status
41902wuffs_png__decoder__decode_frame_config(
41903 wuffs_png__decoder* self,
41904 wuffs_base__frame_config* a_dst,
41905 wuffs_base__io_buffer* a_src) {
41906 if (!self) {
41907 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
41908 }
41909 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
41910 return wuffs_base__make_status(
41911 (self->private_impl.magic == WUFFS_BASE__DISABLED)
41912 ? wuffs_base__error__disabled_by_previous_error
41913 : wuffs_base__error__initialize_not_called);
41914 }
41915 if (!a_src) {
41916 self->private_impl.magic = WUFFS_BASE__DISABLED;
41917 return wuffs_base__make_status(wuffs_base__error__bad_argument);
41918 }
41919 if ((self->private_impl.active_coroutine != 0) &&
41920 (self->private_impl.active_coroutine != 2)) {
41921 self->private_impl.magic = WUFFS_BASE__DISABLED;
41922 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
41923 }
41924 self->private_impl.active_coroutine = 0;
41925 wuffs_base__status status = wuffs_base__make_status(NULL);
41926
Nigel Tao123a5c62022-06-03 14:17:20 +100041927 uint32_t v_checksum_have = 0;
41928
Nigel Taoe360a532021-04-05 22:47:03 +100041929 const uint8_t* iop_a_src = NULL;
41930 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41931 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
41932 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110041933 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100041934 io0_a_src = a_src->data.ptr;
41935 io1_a_src = io0_a_src + a_src->meta.ri;
41936 iop_a_src = io1_a_src;
41937 io2_a_src = io0_a_src + a_src->meta.wi;
41938 }
41939
41940 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
41941 switch (coro_susp_point) {
41942 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
41943
Nigel Tao123a5c62022-06-03 14:17:20 +100041944 if ((self->private_impl.f_call_sequence & 16) != 0) {
41945 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
41946 goto exit;
41947 } else if (self->private_impl.f_call_sequence == 32) {
41948 } else if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100041949 if (a_src) {
41950 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41951 }
41952 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
41953 status = wuffs_png__decoder__decode_image_config(self, NULL, a_src);
41954 if (a_src) {
41955 iop_a_src = a_src->data.ptr + a_src->meta.ri;
41956 }
41957 if (status.repr) {
41958 goto suspend;
41959 }
Nigel Tao123a5c62022-06-03 14:17:20 +100041960 } else if (self->private_impl.f_call_sequence == 40) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100041961 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 +100041962 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
41963 goto exit;
41964 }
Nigel Tao123a5c62022-06-03 14:17:20 +100041965 } else if (self->private_impl.f_call_sequence == 64) {
Nigel Taobf9dab32021-11-18 19:19:55 +110041966 if (a_src) {
41967 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
41968 }
41969 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
41970 status = wuffs_png__decoder__skip_frame(self, a_src);
41971 if (a_src) {
41972 iop_a_src = a_src->data.ptr + a_src->meta.ri;
41973 }
41974 if (status.repr) {
41975 goto suspend;
41976 }
Nigel Tao123a5c62022-06-03 14:17:20 +100041977 } else {
41978 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
41979 goto ok;
41980 }
41981 if (self->private_impl.f_metadata_fourcc != 0) {
41982 self->private_impl.f_call_sequence = 48;
41983 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
41984 goto ok;
Nigel Taobf9dab32021-11-18 19:19:55 +110041985 }
41986 if (self->private_impl.f_num_decoded_frame_configs_value == 0) {
41987 self->private_impl.f_frame_rect_x0 = self->private_impl.f_first_rect_x0;
41988 self->private_impl.f_frame_rect_y0 = self->private_impl.f_first_rect_y0;
41989 self->private_impl.f_frame_rect_x1 = self->private_impl.f_first_rect_x1;
41990 self->private_impl.f_frame_rect_y1 = self->private_impl.f_first_rect_y1;
41991 self->private_impl.f_frame_config_io_position = self->private_impl.f_first_config_io_position;
41992 self->private_impl.f_frame_duration = self->private_impl.f_first_duration;
41993 self->private_impl.f_frame_disposal = self->private_impl.f_first_disposal;
41994 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 +100041995 } else {
Nigel Taobf9dab32021-11-18 19:19:55 +110041996 while (true) {
41997 {
41998 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
41999 uint32_t t_0;
42000 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42001 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42002 iop_a_src += 4;
42003 } else {
42004 self->private_data.s_decode_frame_config[0].scratch = 0;
42005 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
42006 while (true) {
42007 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42008 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42009 goto suspend;
42010 }
42011 uint64_t* scratch = &self->private_data.s_decode_frame_config[0].scratch;
42012 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
42013 *scratch >>= 8;
42014 *scratch <<= 8;
42015 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
42016 if (num_bits_0 == 24) {
42017 t_0 = ((uint32_t)(*scratch >> 32));
42018 break;
42019 }
42020 num_bits_0 += 8;
42021 *scratch |= ((uint64_t)(num_bits_0));
42022 }
42023 }
42024 self->private_impl.f_chunk_length = t_0;
42025 }
42026 {
42027 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
42028 uint32_t t_1;
42029 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42030 t_1 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
42031 iop_a_src += 4;
42032 } else {
42033 self->private_data.s_decode_frame_config[0].scratch = 0;
42034 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
42035 while (true) {
42036 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42037 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42038 goto suspend;
42039 }
42040 uint64_t* scratch = &self->private_data.s_decode_frame_config[0].scratch;
42041 uint32_t num_bits_1 = ((uint32_t)(*scratch >> 56));
42042 *scratch <<= 8;
42043 *scratch >>= 8;
42044 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_1;
42045 if (num_bits_1 == 24) {
42046 t_1 = ((uint32_t)(*scratch));
42047 break;
42048 }
42049 num_bits_1 += 8;
42050 *scratch |= ((uint64_t)(num_bits_1)) << 56;
42051 }
42052 }
42053 self->private_impl.f_chunk_type = t_1;
42054 }
Nigel Tao123a5c62022-06-03 14:17:20 +100042055 if (self->private_impl.f_chunk_type == 1145980233) {
42056 if (self->private_impl.f_chunk_length != 0) {
42057 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42058 goto exit;
42059 }
42060 {
42061 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
42062 uint32_t t_2;
42063 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42064 t_2 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
42065 iop_a_src += 4;
42066 } else {
42067 self->private_data.s_decode_frame_config[0].scratch = 0;
42068 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
42069 while (true) {
42070 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42071 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42072 goto suspend;
42073 }
42074 uint64_t* scratch = &self->private_data.s_decode_frame_config[0].scratch;
42075 uint32_t num_bits_2 = ((uint32_t)(*scratch >> 56));
42076 *scratch <<= 8;
42077 *scratch >>= 8;
42078 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_2;
42079 if (num_bits_2 == 24) {
42080 t_2 = ((uint32_t)(*scratch));
42081 break;
42082 }
42083 num_bits_2 += 8;
42084 *scratch |= ((uint64_t)(num_bits_2)) << 56;
42085 }
42086 }
42087 v_checksum_have = t_2;
42088 }
42089 if ( ! self->private_impl.f_ignore_checksum && (v_checksum_have != 2187346606)) {
42090 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
42091 goto exit;
42092 }
42093 self->private_impl.f_call_sequence = 96;
42094 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
42095 goto ok;
42096 } else if (self->private_impl.f_chunk_type == 1413571686) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042097 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42098 goto exit;
42099 } else if (self->private_impl.f_chunk_type == 1280598886) {
42100 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));
42101 if (a_src) {
42102 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42103 }
Nigel Tao123a5c62022-06-03 14:17:20 +100042104 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
Nigel Taobf9dab32021-11-18 19:19:55 +110042105 status = wuffs_png__decoder__decode_fctl(self, a_src);
42106 if (a_src) {
42107 iop_a_src = a_src->data.ptr + a_src->meta.ri;
42108 }
42109 if (status.repr) {
42110 goto suspend;
42111 }
42112 self->private_data.s_decode_frame_config[0].scratch = 4;
Nigel Tao123a5c62022-06-03 14:17:20 +100042113 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
Nigel Taobf9dab32021-11-18 19:19:55 +110042114 if (self->private_data.s_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
42115 self->private_data.s_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
42116 iop_a_src = io2_a_src;
42117 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42118 goto suspend;
42119 }
42120 iop_a_src += self->private_data.s_decode_frame_config[0].scratch;
42121 goto label__0__break;
42122 }
Nigel Tao123a5c62022-06-03 14:17:20 +100042123 if (a_src) {
42124 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42125 }
42126 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
42127 status = wuffs_png__decoder__decode_other_chunk(self, a_src, true);
42128 if (a_src) {
42129 iop_a_src = a_src->data.ptr + a_src->meta.ri;
42130 }
42131 if (status.repr) {
42132 goto suspend;
42133 }
42134 if (self->private_impl.f_metadata_fourcc != 0) {
42135 self->private_impl.f_call_sequence = 48;
42136 status = wuffs_base__make_status(wuffs_base__note__metadata_reported);
42137 goto ok;
42138 }
42139 self->private_data.s_decode_frame_config[0].scratch = 4;
42140 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
Nigel Taobf9dab32021-11-18 19:19:55 +110042141 if (self->private_data.s_decode_frame_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
42142 self->private_data.s_decode_frame_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
42143 iop_a_src = io2_a_src;
42144 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42145 goto suspend;
42146 }
42147 iop_a_src += self->private_data.s_decode_frame_config[0].scratch;
42148 self->private_impl.f_chunk_length = 0;
42149 }
42150 label__0__break:;
Nigel Taoe360a532021-04-05 22:47:03 +100042151 }
42152 if (a_dst != NULL) {
42153 wuffs_base__frame_config__set(
42154 a_dst,
42155 wuffs_base__utility__make_rect_ie_u32(
Nigel Taobf9dab32021-11-18 19:19:55 +110042156 self->private_impl.f_frame_rect_x0,
42157 self->private_impl.f_frame_rect_y0,
42158 self->private_impl.f_frame_rect_x1,
42159 self->private_impl.f_frame_rect_y1),
42160 ((wuffs_base__flicks)(self->private_impl.f_frame_duration)),
42161 ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value)),
Nigel Taoe360a532021-04-05 22:47:03 +100042162 self->private_impl.f_frame_config_io_position,
Nigel Taobf9dab32021-11-18 19:19:55 +110042163 self->private_impl.f_frame_disposal,
42164 ((self->private_impl.f_color_type <= 3) && ! self->private_impl.f_seen_trns),
42165 self->private_impl.f_frame_overwrite_instead_of_blend,
Nigel Taoe360a532021-04-05 22:47:03 +100042166 0);
42167 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042168 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frame_configs_value, 1);
Nigel Tao123a5c62022-06-03 14:17:20 +100042169 self->private_impl.f_call_sequence = 64;
Nigel Taoe360a532021-04-05 22:47:03 +100042170
Nigel Taoe360a532021-04-05 22:47:03 +100042171 ok:
42172 self->private_impl.p_decode_frame_config[0] = 0;
42173 goto exit;
42174 }
42175
42176 goto suspend;
42177 suspend:
42178 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
42179 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
42180
42181 goto exit;
42182 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110042183 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100042184 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42185 }
42186
42187 if (wuffs_base__status__is_error(&status)) {
42188 self->private_impl.magic = WUFFS_BASE__DISABLED;
42189 }
42190 return status;
42191}
42192
Nigel Taobf9dab32021-11-18 19:19:55 +110042193// -------- func png.decoder.skip_frame
42194
42195static wuffs_base__status
42196wuffs_png__decoder__skip_frame(
42197 wuffs_png__decoder* self,
42198 wuffs_base__io_buffer* a_src) {
42199 wuffs_base__status status = wuffs_base__make_status(NULL);
42200
42201 uint32_t v_seq_num = 0;
42202
42203 const uint8_t* iop_a_src = NULL;
42204 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42205 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42206 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110042207 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042208 io0_a_src = a_src->data.ptr;
42209 io1_a_src = io0_a_src + a_src->meta.ri;
42210 iop_a_src = io1_a_src;
42211 io2_a_src = io0_a_src + a_src->meta.wi;
42212 }
42213
42214 uint32_t coro_susp_point = self->private_impl.p_skip_frame[0];
42215 switch (coro_susp_point) {
42216 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
42217
42218 self->private_impl.f_chunk_type_array[0] = 0;
42219 self->private_impl.f_chunk_type_array[1] = 0;
42220 self->private_impl.f_chunk_type_array[2] = 0;
42221 self->private_impl.f_chunk_type_array[3] = 0;
42222 label__0__continue:;
42223 while (true) {
42224 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
42225 if (a_src && a_src->meta.closed) {
42226 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42227 goto exit;
42228 }
42229 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42230 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
42231 }
42232 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42233 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
42234 if (self->private_impl.f_chunk_type == 1413563465) {
42235 if (self->private_impl.f_chunk_type_array[0] == 102) {
42236 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42237 goto exit;
42238 }
42239 self->private_impl.f_chunk_type_array[0] = 73;
42240 self->private_impl.f_chunk_type_array[1] = 68;
42241 self->private_impl.f_chunk_type_array[2] = 65;
42242 self->private_impl.f_chunk_type_array[3] = 84;
42243 } else if (self->private_impl.f_chunk_type == 1413571686) {
42244 if (self->private_impl.f_chunk_type_array[0] == 73) {
42245 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42246 goto exit;
42247 }
42248 self->private_impl.f_chunk_type_array[0] = 102;
42249 self->private_impl.f_chunk_type_array[1] = 100;
42250 self->private_impl.f_chunk_type_array[2] = 65;
42251 self->private_impl.f_chunk_type_array[3] = 84;
42252 if (self->private_impl.f_chunk_length < 4) {
42253 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42254 goto exit;
42255 }
42256 self->private_impl.f_chunk_length -= 4;
42257 iop_a_src += 8;
42258 {
42259 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
42260 uint32_t t_0;
42261 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42262 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42263 iop_a_src += 4;
42264 } else {
42265 self->private_data.s_skip_frame[0].scratch = 0;
42266 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
42267 while (true) {
42268 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42269 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42270 goto suspend;
42271 }
42272 uint64_t* scratch = &self->private_data.s_skip_frame[0].scratch;
42273 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
42274 *scratch >>= 8;
42275 *scratch <<= 8;
42276 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
42277 if (num_bits_0 == 24) {
42278 t_0 = ((uint32_t)(*scratch >> 32));
42279 break;
42280 }
42281 num_bits_0 += 8;
42282 *scratch |= ((uint64_t)(num_bits_0));
42283 }
42284 }
42285 v_seq_num = t_0;
42286 }
42287 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
42288 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
42289 goto exit;
42290 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
42291 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
42292 goto exit;
42293 }
42294 self->private_impl.f_next_animation_seq_num += 1;
42295 self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 4);
42296 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
42297 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
42298 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
42299 iop_a_src = io2_a_src;
42300 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42301 goto suspend;
42302 }
42303 iop_a_src += self->private_data.s_skip_frame[0].scratch;
42304 self->private_impl.f_chunk_length = 0;
42305 goto label__0__continue;
42306 } else if (self->private_impl.f_chunk_type_array[0] != 0) {
42307 goto label__0__break;
42308 } else if (self->private_impl.f_chunk_type == 1280598886) {
42309 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42310 goto exit;
42311 }
42312 self->private_data.s_skip_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12);
42313 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
42314 if (self->private_data.s_skip_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
42315 self->private_data.s_skip_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
42316 iop_a_src = io2_a_src;
42317 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42318 goto suspend;
42319 }
42320 iop_a_src += self->private_data.s_skip_frame[0].scratch;
42321 self->private_impl.f_chunk_length = 0;
42322 }
42323 label__0__break:;
42324 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
Nigel Tao123a5c62022-06-03 14:17:20 +100042325 self->private_impl.f_call_sequence = 32;
Nigel Taobf9dab32021-11-18 19:19:55 +110042326
42327 ok:
42328 self->private_impl.p_skip_frame[0] = 0;
42329 goto exit;
42330 }
42331
42332 goto suspend;
42333 suspend:
42334 self->private_impl.p_skip_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
42335
42336 goto exit;
42337 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110042338 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042339 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42340 }
42341
42342 return status;
42343}
42344
Nigel Taoe360a532021-04-05 22:47:03 +100042345// -------- func png.decoder.decode_frame
42346
42347WUFFS_BASE__MAYBE_STATIC wuffs_base__status
42348wuffs_png__decoder__decode_frame(
42349 wuffs_png__decoder* self,
42350 wuffs_base__pixel_buffer* a_dst,
42351 wuffs_base__io_buffer* a_src,
42352 wuffs_base__pixel_blend a_blend,
42353 wuffs_base__slice_u8 a_workbuf,
42354 wuffs_base__decode_frame_options* a_opts) {
42355 if (!self) {
42356 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
42357 }
42358 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
42359 return wuffs_base__make_status(
42360 (self->private_impl.magic == WUFFS_BASE__DISABLED)
42361 ? wuffs_base__error__disabled_by_previous_error
42362 : wuffs_base__error__initialize_not_called);
42363 }
42364 if (!a_dst || !a_src) {
42365 self->private_impl.magic = WUFFS_BASE__DISABLED;
42366 return wuffs_base__make_status(wuffs_base__error__bad_argument);
42367 }
42368 if ((self->private_impl.active_coroutine != 0) &&
42369 (self->private_impl.active_coroutine != 3)) {
42370 self->private_impl.magic = WUFFS_BASE__DISABLED;
42371 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
42372 }
42373 self->private_impl.active_coroutine = 0;
42374 wuffs_base__status status = wuffs_base__make_status(NULL);
42375
Nigel Taobf9dab32021-11-18 19:19:55 +110042376 uint32_t v_seq_num = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100042377 wuffs_base__status v_status = wuffs_base__make_status(NULL);
42378 uint32_t v_pass_width = 0;
42379 uint32_t v_pass_height = 0;
42380
Nigel Taobf9dab32021-11-18 19:19:55 +110042381 const uint8_t* iop_a_src = NULL;
42382 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42383 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42384 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110042385 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042386 io0_a_src = a_src->data.ptr;
42387 io1_a_src = io0_a_src + a_src->meta.ri;
42388 iop_a_src = io1_a_src;
42389 io2_a_src = io0_a_src + a_src->meta.wi;
42390 }
42391
Nigel Taoe360a532021-04-05 22:47:03 +100042392 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
42393 switch (coro_susp_point) {
42394 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
42395
Nigel Tao123a5c62022-06-03 14:17:20 +100042396 if ((self->private_impl.f_call_sequence & 16) != 0) {
42397 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
42398 goto exit;
42399 } else if (self->private_impl.f_call_sequence >= 96) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042400 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
42401 goto ok;
Nigel Tao123a5c62022-06-03 14:17:20 +100042402 } else if (self->private_impl.f_call_sequence != 64) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042403 if (a_src) {
42404 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42405 }
Nigel Taoe360a532021-04-05 22:47:03 +100042406 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
42407 status = wuffs_png__decoder__decode_frame_config(self, NULL, a_src);
Nigel Taobf9dab32021-11-18 19:19:55 +110042408 if (a_src) {
42409 iop_a_src = a_src->data.ptr + a_src->meta.ri;
42410 }
Nigel Taoe360a532021-04-05 22:47:03 +100042411 if (status.repr) {
42412 goto suspend;
42413 }
Nigel Taoe360a532021-04-05 22:47:03 +100042414 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042415 while (true) {
42416 while (((uint64_t)(io2_a_src - iop_a_src)) < 8) {
42417 if (a_src && a_src->meta.closed) {
42418 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42419 goto exit;
42420 }
42421 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42422 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
42423 }
42424 self->private_impl.f_chunk_length = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42425 self->private_impl.f_chunk_type = ((uint32_t)((wuffs_base__peek_u64le__no_bounds_check(iop_a_src) >> 32)));
42426 if (self->private_impl.f_chunk_type == 1413563465) {
42427 self->private_impl.f_chunk_type_array[0] = 73;
42428 self->private_impl.f_chunk_type_array[1] = 68;
42429 self->private_impl.f_chunk_type_array[2] = 65;
42430 self->private_impl.f_chunk_type_array[3] = 84;
42431 iop_a_src += 8;
42432 if ( ! self->private_impl.f_ignore_checksum) {
42433 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
42434 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
42435 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
42436 }
42437 goto label__0__break;
42438 } else if (self->private_impl.f_chunk_type == 1413571686) {
42439 self->private_impl.f_chunk_type_array[0] = 102;
42440 self->private_impl.f_chunk_type_array[1] = 100;
42441 self->private_impl.f_chunk_type_array[2] = 65;
42442 self->private_impl.f_chunk_type_array[3] = 84;
42443 if (self->private_impl.f_chunk_length < 4) {
42444 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42445 goto exit;
42446 }
42447 self->private_impl.f_chunk_length -= 4;
42448 iop_a_src += 8;
42449 {
42450 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
42451 uint32_t t_0;
42452 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42453 t_0 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42454 iop_a_src += 4;
42455 } else {
42456 self->private_data.s_decode_frame[0].scratch = 0;
42457 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
42458 while (true) {
42459 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42460 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42461 goto suspend;
42462 }
42463 uint64_t* scratch = &self->private_data.s_decode_frame[0].scratch;
42464 uint32_t num_bits_0 = ((uint32_t)(*scratch & 0xFF));
42465 *scratch >>= 8;
42466 *scratch <<= 8;
42467 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_0);
42468 if (num_bits_0 == 24) {
42469 t_0 = ((uint32_t)(*scratch >> 32));
42470 break;
42471 }
42472 num_bits_0 += 8;
42473 *scratch |= ((uint64_t)(num_bits_0));
42474 }
42475 }
42476 v_seq_num = t_0;
42477 }
42478 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
42479 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
42480 goto exit;
42481 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
42482 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
42483 goto exit;
42484 }
42485 self->private_impl.f_next_animation_seq_num += 1;
42486 goto label__0__break;
42487 } else if (self->private_impl.f_chunk_type == 1280598886) {
42488 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42489 goto exit;
42490 }
42491 self->private_data.s_decode_frame[0].scratch = (((uint64_t)(self->private_impl.f_chunk_length)) + 12);
42492 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
42493 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
42494 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
42495 iop_a_src = io2_a_src;
42496 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42497 goto suspend;
42498 }
42499 iop_a_src += self->private_data.s_decode_frame[0].scratch;
42500 self->private_impl.f_chunk_length = 0;
42501 }
42502 label__0__break:;
42503 if (self->private_impl.f_zlib_is_dirty) {
42504 wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib,
42505 sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
42506 if (self->private_impl.f_ignore_checksum) {
42507 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, 1, true);
42508 }
42509 }
42510 self->private_impl.f_zlib_is_dirty = true;
Nigel Taoe360a532021-04-05 22:47:03 +100042511 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
42512 wuffs_base__pixel_buffer__pixel_format(a_dst),
42513 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)),
42514 wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt),
42515 wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024),
42516 a_blend);
42517 if ( ! wuffs_base__status__is_ok(&v_status)) {
42518 status = v_status;
42519 if (wuffs_base__status__is_error(&status)) {
42520 goto exit;
42521 } else if (wuffs_base__status__is_suspension(&status)) {
42522 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
42523 goto exit;
42524 }
42525 goto ok;
42526 }
Nigel Tao7804ffe2021-10-07 21:58:26 +110042527 self->private_impl.f_workbuf_hist_pos_base = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100042528 while (true) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042529 if (self->private_impl.f_chunk_type_array[0] == 73) {
42530 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]));
42531 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]));
42532 } else {
42533 v_pass_width = (16777215 & ((uint32_t)(self->private_impl.f_frame_rect_x1 - self->private_impl.f_frame_rect_x0)));
42534 v_pass_height = (16777215 & ((uint32_t)(self->private_impl.f_frame_rect_y1 - self->private_impl.f_frame_rect_y0)));
42535 }
Nigel Taoe360a532021-04-05 22:47:03 +100042536 if ((v_pass_width > 0) && (v_pass_height > 0)) {
42537 self->private_impl.f_pass_bytes_per_row = wuffs_png__decoder__calculate_bytes_per_row(self, v_pass_width);
42538 self->private_impl.f_pass_workbuf_length = (((uint64_t)(v_pass_height)) * (1 + self->private_impl.f_pass_bytes_per_row));
Nigel Tao123a5c62022-06-03 14:17:20 +100042539 while (true) {
42540 {
42541 if (a_src) {
42542 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42543 }
42544 wuffs_base__status t_1 = wuffs_png__decoder__decode_pass(self, a_src, a_workbuf);
42545 v_status = t_1;
42546 if (a_src) {
42547 iop_a_src = a_src->data.ptr + a_src->meta.ri;
42548 }
42549 }
42550 if (wuffs_base__status__is_ok(&v_status)) {
42551 goto label__1__break;
42552 } else if (wuffs_base__status__is_error(&v_status) || ((v_status.repr == wuffs_base__suspension__short_read) && (a_src && a_src->meta.closed))) {
42553 if (self->private_impl.f_workbuf_wi <= ((uint64_t)(a_workbuf.len))) {
42554 wuffs_png__decoder__filter_and_swizzle(self, a_dst, wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_workbuf_wi));
42555 }
42556 if (v_status.repr == wuffs_base__suspension__short_read) {
42557 while (true) {
42558 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42559 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
42560 }
42561 }
42562 }
42563 status = v_status;
42564 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
Nigel Taobf9dab32021-11-18 19:19:55 +110042565 }
Nigel Tao123a5c62022-06-03 14:17:20 +100042566 label__1__break:;
Nigel Taoe360a532021-04-05 22:47:03 +100042567 v_status = wuffs_png__decoder__filter_and_swizzle(self, a_dst, a_workbuf);
42568 if ( ! wuffs_base__status__is_ok(&v_status)) {
42569 status = v_status;
42570 if (wuffs_base__status__is_error(&status)) {
42571 goto exit;
42572 } else if (wuffs_base__status__is_suspension(&status)) {
42573 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
42574 goto exit;
42575 }
42576 goto ok;
42577 }
Nigel Tao7804ffe2021-10-07 21:58:26 +110042578 self->private_impl.f_workbuf_hist_pos_base += self->private_impl.f_pass_workbuf_length;
Nigel Taoe360a532021-04-05 22:47:03 +100042579 }
42580 if ((self->private_impl.f_interlace_pass == 0) || (self->private_impl.f_interlace_pass >= 7)) {
Nigel Tao123a5c62022-06-03 14:17:20 +100042581 goto label__2__break;
Nigel Taoe360a532021-04-05 22:47:03 +100042582 }
42583#if defined(__GNUC__)
42584#pragma GCC diagnostic push
42585#pragma GCC diagnostic ignored "-Wconversion"
42586#endif
42587 self->private_impl.f_interlace_pass += 1;
42588#if defined(__GNUC__)
42589#pragma GCC diagnostic pop
42590#endif
42591 }
Nigel Tao123a5c62022-06-03 14:17:20 +100042592 label__2__break:;
Nigel Taobf9dab32021-11-18 19:19:55 +110042593 wuffs_base__u32__sat_add_indirect(&self->private_impl.f_num_decoded_frames_value, 1);
Nigel Tao123a5c62022-06-03 14:17:20 +100042594 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100042595
Nigel Taoe360a532021-04-05 22:47:03 +100042596 ok:
42597 self->private_impl.p_decode_frame[0] = 0;
42598 goto exit;
42599 }
42600
42601 goto suspend;
42602 suspend:
42603 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
42604 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
42605
42606 goto exit;
42607 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110042608 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042609 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42610 }
42611
Nigel Taoe360a532021-04-05 22:47:03 +100042612 if (wuffs_base__status__is_error(&status)) {
42613 self->private_impl.magic = WUFFS_BASE__DISABLED;
42614 }
42615 return status;
42616}
42617
42618// -------- func png.decoder.decode_pass
42619
42620static wuffs_base__status
42621wuffs_png__decoder__decode_pass(
42622 wuffs_png__decoder* self,
42623 wuffs_base__io_buffer* a_src,
42624 wuffs_base__slice_u8 a_workbuf) {
42625 wuffs_base__status status = wuffs_base__make_status(NULL);
42626
42627 wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer();
42628 wuffs_base__io_buffer* v_w = &u_w;
42629 uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42630 uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42631 uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42632 uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42633 uint64_t v_w_mark = 0;
42634 uint64_t v_r_mark = 0;
42635 wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL);
42636 uint32_t v_checksum_have = 0;
42637 uint32_t v_checksum_want = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110042638 uint32_t v_seq_num = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100042639
42640 const uint8_t* iop_a_src = NULL;
42641 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42642 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
42643 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110042644 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100042645 io0_a_src = a_src->data.ptr;
42646 io1_a_src = io0_a_src + a_src->meta.ri;
42647 iop_a_src = io1_a_src;
42648 io2_a_src = io0_a_src + a_src->meta.wi;
42649 }
42650
42651 uint32_t coro_susp_point = self->private_impl.p_decode_pass[0];
Nigel Taoe360a532021-04-05 22:47:03 +100042652 switch (coro_susp_point) {
42653 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
42654
42655 self->private_impl.f_workbuf_wi = 0;
42656 label__0__continue:;
42657 while (true) {
42658 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)))) {
42659 status = wuffs_base__make_status(wuffs_base__error__bad_workbuf_length);
42660 goto exit;
42661 }
42662 {
42663 wuffs_base__io_buffer* o_0_v_w = v_w;
42664 uint8_t *o_0_iop_v_w = iop_v_w;
42665 uint8_t *o_0_io0_v_w = io0_v_w;
42666 uint8_t *o_0_io1_v_w = io1_v_w;
42667 uint8_t *o_0_io2_v_w = io2_v_w;
42668 v_w = wuffs_base__io_writer__set(
42669 &u_w,
42670 &iop_v_w,
42671 &io0_v_w,
42672 &io1_v_w,
42673 &io2_v_w,
42674 wuffs_base__slice_u8__subslice_ij(a_workbuf,
42675 self->private_impl.f_workbuf_wi,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100042676 self->private_impl.f_pass_workbuf_length),
Nigel Tao7804ffe2021-10-07 21:58:26 +110042677 ((uint64_t)(self->private_impl.f_workbuf_hist_pos_base + self->private_impl.f_workbuf_wi)));
Nigel Taoe360a532021-04-05 22:47:03 +100042678 {
42679 const uint8_t *o_1_io2_a_src = io2_a_src;
42680 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
Nigel Taobf9dab32021-11-18 19:19:55 +110042681 ((uint64_t)(self->private_impl.f_chunk_length)));
Nigel Taoe360a532021-04-05 22:47:03 +100042682 if (a_src) {
42683 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
42684 }
42685 v_w_mark = ((uint64_t)(iop_v_w - io0_v_w));
42686 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
42687 {
42688 u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr));
42689 if (a_src) {
42690 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42691 }
42692 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());
42693 v_zlib_status = t_0;
42694 iop_v_w = u_w.data.ptr + u_w.meta.wi;
42695 if (a_src) {
42696 iop_a_src = a_src->data.ptr + a_src->meta.ri;
42697 }
42698 }
42699 if ( ! self->private_impl.f_ignore_checksum) {
42700 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));
42701 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042702 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 +100042703 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))));
42704 io2_a_src = o_1_io2_a_src;
42705 if (a_src) {
42706 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
42707 }
42708 }
42709 v_w = o_0_v_w;
42710 iop_v_w = o_0_iop_v_w;
42711 io0_v_w = o_0_io0_v_w;
42712 io1_v_w = o_0_io1_v_w;
42713 io2_v_w = o_0_io2_v_w;
42714 }
42715 if (wuffs_base__status__is_ok(&v_zlib_status)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042716 if (self->private_impl.f_chunk_length > 0) {
42717 status = wuffs_base__make_status(wuffs_base__error__too_much_data);
42718 goto exit;
42719 }
42720 {
42721 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
42722 uint32_t t_1;
42723 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42724 t_1 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42725 iop_a_src += 4;
42726 } else {
42727 self->private_data.s_decode_pass[0].scratch = 0;
42728 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
42729 while (true) {
42730 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42731 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42732 goto suspend;
Nigel Taoe360a532021-04-05 22:47:03 +100042733 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042734 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
42735 uint32_t num_bits_1 = ((uint32_t)(*scratch & 0xFF));
42736 *scratch >>= 8;
42737 *scratch <<= 8;
42738 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_1);
42739 if (num_bits_1 == 24) {
42740 t_1 = ((uint32_t)(*scratch >> 32));
42741 break;
42742 }
42743 num_bits_1 += 8;
42744 *scratch |= ((uint64_t)(num_bits_1));
Nigel Taoe360a532021-04-05 22:47:03 +100042745 }
Nigel Taoe360a532021-04-05 22:47:03 +100042746 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042747 v_checksum_want = t_1;
42748 }
42749 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0] == 73)) {
42750 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 +100042751 if (v_checksum_have != v_checksum_want) {
42752 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
42753 goto exit;
42754 }
42755 }
42756 goto label__0__break;
42757 } else if (v_zlib_status.repr == wuffs_base__suspension__short_write) {
42758 if ((1 <= self->private_impl.f_interlace_pass) && (self->private_impl.f_interlace_pass <= 6)) {
42759 goto label__0__break;
42760 }
42761 status = wuffs_base__make_status(wuffs_base__error__too_much_data);
42762 goto exit;
42763 } else if (v_zlib_status.repr != wuffs_base__suspension__short_read) {
42764 status = v_zlib_status;
42765 if (wuffs_base__status__is_error(&status)) {
42766 goto exit;
42767 } else if (wuffs_base__status__is_suspension(&status)) {
42768 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
42769 goto exit;
42770 }
42771 goto ok;
42772 } else if (self->private_impl.f_chunk_length == 0) {
42773 {
42774 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
42775 uint32_t t_2;
42776 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42777 t_2 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42778 iop_a_src += 4;
42779 } else {
42780 self->private_data.s_decode_pass[0].scratch = 0;
42781 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
42782 while (true) {
42783 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42784 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42785 goto suspend;
42786 }
42787 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
42788 uint32_t num_bits_2 = ((uint32_t)(*scratch & 0xFF));
42789 *scratch >>= 8;
42790 *scratch <<= 8;
42791 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_2);
42792 if (num_bits_2 == 24) {
42793 t_2 = ((uint32_t)(*scratch >> 32));
42794 break;
42795 }
42796 num_bits_2 += 8;
42797 *scratch |= ((uint64_t)(num_bits_2));
42798 }
42799 }
42800 v_checksum_want = t_2;
42801 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042802 if ( ! self->private_impl.f_ignore_checksum && (self->private_impl.f_chunk_type_array[0] == 73)) {
Nigel Taoe360a532021-04-05 22:47:03 +100042803 v_checksum_have = wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__utility__empty_slice_u8());
42804 if (v_checksum_have != v_checksum_want) {
42805 status = wuffs_base__make_status(wuffs_png__error__bad_checksum);
42806 goto exit;
42807 }
42808 }
42809 {
42810 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
Nigel Taobf9dab32021-11-18 19:19:55 +110042811 uint32_t t_3;
Nigel Taoe360a532021-04-05 22:47:03 +100042812 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042813 t_3 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
Nigel Taoe360a532021-04-05 22:47:03 +100042814 iop_a_src += 4;
42815 } else {
42816 self->private_data.s_decode_pass[0].scratch = 0;
42817 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
42818 while (true) {
42819 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42820 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42821 goto suspend;
42822 }
42823 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
42824 uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
42825 *scratch >>= 8;
42826 *scratch <<= 8;
42827 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
42828 if (num_bits_3 == 24) {
Nigel Taobf9dab32021-11-18 19:19:55 +110042829 t_3 = ((uint32_t)(*scratch >> 32));
Nigel Taoe360a532021-04-05 22:47:03 +100042830 break;
42831 }
42832 num_bits_3 += 8;
42833 *scratch |= ((uint64_t)(num_bits_3));
42834 }
42835 }
42836 self->private_impl.f_chunk_length = t_3;
42837 }
42838 {
42839 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
42840 uint32_t t_4;
42841 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42842 t_4 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
42843 iop_a_src += 4;
42844 } else {
42845 self->private_data.s_decode_pass[0].scratch = 0;
42846 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
42847 while (true) {
42848 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42849 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42850 goto suspend;
42851 }
42852 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
42853 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
42854 *scratch <<= 8;
42855 *scratch >>= 8;
42856 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
42857 if (num_bits_4 == 24) {
42858 t_4 = ((uint32_t)(*scratch));
42859 break;
42860 }
42861 num_bits_4 += 8;
42862 *scratch |= ((uint64_t)(num_bits_4)) << 56;
42863 }
42864 }
42865 self->private_impl.f_chunk_type = t_4;
42866 }
Nigel Taobf9dab32021-11-18 19:19:55 +110042867 if (self->private_impl.f_chunk_type_array[0] == 73) {
42868 if (self->private_impl.f_chunk_type != 1413563465) {
42869 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42870 goto exit;
42871 }
42872 if ( ! self->private_impl.f_ignore_checksum) {
42873 wuffs_base__ignore_status(wuffs_crc32__ieee_hasher__initialize(&self->private_data.f_crc32,
42874 sizeof (wuffs_crc32__ieee_hasher), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
42875 wuffs_crc32__ieee_hasher__update_u32(&self->private_data.f_crc32, wuffs_base__make_slice_u8(self->private_impl.f_chunk_type_array, 4));
42876 }
42877 } else {
42878 if ((self->private_impl.f_chunk_type != 1413571686) || (self->private_impl.f_chunk_length < 4)) {
42879 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
42880 goto exit;
42881 }
42882 self->private_impl.f_chunk_length -= 4;
42883 {
42884 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
42885 uint32_t t_5;
42886 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
42887 t_5 = wuffs_base__peek_u32be__no_bounds_check(iop_a_src);
42888 iop_a_src += 4;
42889 } else {
42890 self->private_data.s_decode_pass[0].scratch = 0;
42891 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
42892 while (true) {
42893 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
42894 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
42895 goto suspend;
42896 }
42897 uint64_t* scratch = &self->private_data.s_decode_pass[0].scratch;
42898 uint32_t num_bits_5 = ((uint32_t)(*scratch & 0xFF));
42899 *scratch >>= 8;
42900 *scratch <<= 8;
42901 *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_5);
42902 if (num_bits_5 == 24) {
42903 t_5 = ((uint32_t)(*scratch >> 32));
42904 break;
42905 }
42906 num_bits_5 += 8;
42907 *scratch |= ((uint64_t)(num_bits_5));
42908 }
42909 }
42910 v_seq_num = t_5;
42911 }
42912 if (v_seq_num != self->private_impl.f_next_animation_seq_num) {
42913 status = wuffs_base__make_status(wuffs_png__error__bad_animation_sequence_number);
42914 goto exit;
42915 } else if (self->private_impl.f_next_animation_seq_num >= 4294967295) {
42916 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_file);
42917 goto exit;
42918 }
42919 self->private_impl.f_next_animation_seq_num += 1;
Nigel Taoe360a532021-04-05 22:47:03 +100042920 }
42921 goto label__0__continue;
42922 } else if (((uint64_t)(io2_a_src - iop_a_src)) > 0) {
42923 status = wuffs_base__make_status(wuffs_png__error__internal_error_zlib_decoder_did_not_exhaust_its_input);
42924 goto exit;
42925 }
42926 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
Nigel Taobf9dab32021-11-18 19:19:55 +110042927 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
Nigel Taoe360a532021-04-05 22:47:03 +100042928 }
42929 label__0__break:;
42930 if (self->private_impl.f_workbuf_wi != self->private_impl.f_pass_workbuf_length) {
42931 status = wuffs_base__make_status(wuffs_base__error__not_enough_data);
42932 goto exit;
42933 } else if (0 < ((uint64_t)(a_workbuf.len))) {
42934 if (a_workbuf.ptr[0] == 4) {
42935 a_workbuf.ptr[0] = 1;
42936 }
42937 }
42938
Nigel Taoe360a532021-04-05 22:47:03 +100042939 ok:
42940 self->private_impl.p_decode_pass[0] = 0;
42941 goto exit;
42942 }
42943
42944 goto suspend;
42945 suspend:
42946 self->private_impl.p_decode_pass[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
Nigel Taoe360a532021-04-05 22:47:03 +100042947
42948 goto exit;
42949 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110042950 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100042951 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
42952 }
42953
42954 return status;
42955}
42956
42957// -------- func png.decoder.frame_dirty_rect
42958
42959WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
42960wuffs_png__decoder__frame_dirty_rect(
42961 const wuffs_png__decoder* self) {
42962 if (!self) {
42963 return wuffs_base__utility__empty_rect_ie_u32();
42964 }
42965 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
42966 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
42967 return wuffs_base__utility__empty_rect_ie_u32();
42968 }
42969
42970 return wuffs_base__utility__make_rect_ie_u32(
Nigel Taobf9dab32021-11-18 19:19:55 +110042971 self->private_impl.f_frame_rect_x0,
42972 self->private_impl.f_frame_rect_y0,
42973 self->private_impl.f_frame_rect_x1,
42974 self->private_impl.f_frame_rect_y1);
Nigel Taoe360a532021-04-05 22:47:03 +100042975}
42976
42977// -------- func png.decoder.num_animation_loops
42978
42979WUFFS_BASE__MAYBE_STATIC uint32_t
42980wuffs_png__decoder__num_animation_loops(
42981 const wuffs_png__decoder* self) {
42982 if (!self) {
42983 return 0;
42984 }
42985 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
42986 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
42987 return 0;
42988 }
42989
Nigel Taobf9dab32021-11-18 19:19:55 +110042990 return self->private_impl.f_num_animation_loops_value;
Nigel Taoe360a532021-04-05 22:47:03 +100042991}
42992
42993// -------- func png.decoder.num_decoded_frame_configs
42994
42995WUFFS_BASE__MAYBE_STATIC uint64_t
42996wuffs_png__decoder__num_decoded_frame_configs(
42997 const wuffs_png__decoder* self) {
42998 if (!self) {
42999 return 0;
43000 }
43001 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
43002 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
43003 return 0;
43004 }
43005
Nigel Taobf9dab32021-11-18 19:19:55 +110043006 return ((uint64_t)(self->private_impl.f_num_decoded_frame_configs_value));
Nigel Taoe360a532021-04-05 22:47:03 +100043007}
43008
43009// -------- func png.decoder.num_decoded_frames
43010
43011WUFFS_BASE__MAYBE_STATIC uint64_t
43012wuffs_png__decoder__num_decoded_frames(
43013 const wuffs_png__decoder* self) {
43014 if (!self) {
43015 return 0;
43016 }
43017 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
43018 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
43019 return 0;
43020 }
43021
Nigel Taobf9dab32021-11-18 19:19:55 +110043022 return ((uint64_t)(self->private_impl.f_num_decoded_frames_value));
Nigel Taoe360a532021-04-05 22:47:03 +100043023}
43024
43025// -------- func png.decoder.restart_frame
43026
43027WUFFS_BASE__MAYBE_STATIC wuffs_base__status
43028wuffs_png__decoder__restart_frame(
43029 wuffs_png__decoder* self,
43030 uint64_t a_index,
43031 uint64_t a_io_position) {
43032 if (!self) {
43033 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
43034 }
43035 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
43036 return wuffs_base__make_status(
43037 (self->private_impl.magic == WUFFS_BASE__DISABLED)
43038 ? wuffs_base__error__disabled_by_previous_error
43039 : wuffs_base__error__initialize_not_called);
43040 }
43041
Nigel Tao123a5c62022-06-03 14:17:20 +100043042 if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100043043 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
Nigel Taobf9dab32021-11-18 19:19:55 +110043044 } 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 +100043045 return wuffs_base__make_status(wuffs_base__error__bad_argument);
43046 }
Nigel Tao123a5c62022-06-03 14:17:20 +100043047 self->private_impl.f_call_sequence = 40;
Nigel Taoe360a532021-04-05 22:47:03 +100043048 if (self->private_impl.f_interlace_pass >= 1) {
43049 self->private_impl.f_interlace_pass = 1;
43050 }
43051 self->private_impl.f_frame_config_io_position = a_io_position;
Nigel Taobf9dab32021-11-18 19:19:55 +110043052 self->private_impl.f_num_decoded_frame_configs_value = ((uint32_t)((a_index & 4294967295)));
43053 self->private_impl.f_num_decoded_frames_value = self->private_impl.f_num_decoded_frame_configs_value;
Nigel Taoe360a532021-04-05 22:47:03 +100043054 return wuffs_base__make_status(NULL);
43055}
43056
43057// -------- func png.decoder.set_report_metadata
43058
43059WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
43060wuffs_png__decoder__set_report_metadata(
43061 wuffs_png__decoder* self,
43062 uint32_t a_fourcc,
43063 bool a_report) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043064 if (!self) {
43065 return wuffs_base__make_empty_struct();
43066 }
43067 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
43068 return wuffs_base__make_empty_struct();
43069 }
43070
43071 if (a_fourcc == 1128813133) {
43072 self->private_impl.f_report_metadata_chrm = a_report;
Nigel Taoebbecaa2022-01-08 14:08:27 +110043073 } else if (a_fourcc == 1163413830) {
43074 self->private_impl.f_report_metadata_exif = a_report;
Nigel Taobf9dab32021-11-18 19:19:55 +110043075 } else if (a_fourcc == 1195461953) {
43076 self->private_impl.f_report_metadata_gama = a_report;
43077 } else if (a_fourcc == 1229144912) {
43078 self->private_impl.f_report_metadata_iccp = a_report;
43079 } else if (a_fourcc == 1263947808) {
43080 self->private_impl.f_report_metadata_kvp = a_report;
43081 } else if (a_fourcc == 1397901122) {
43082 self->private_impl.f_report_metadata_srgb = a_report;
43083 }
Nigel Taoe360a532021-04-05 22:47:03 +100043084 return wuffs_base__make_empty_struct();
43085}
43086
43087// -------- func png.decoder.tell_me_more
43088
43089WUFFS_BASE__MAYBE_STATIC wuffs_base__status
43090wuffs_png__decoder__tell_me_more(
43091 wuffs_png__decoder* self,
43092 wuffs_base__io_buffer* a_dst,
43093 wuffs_base__more_information* a_minfo,
43094 wuffs_base__io_buffer* a_src) {
43095 if (!self) {
43096 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
43097 }
43098 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
43099 return wuffs_base__make_status(
43100 (self->private_impl.magic == WUFFS_BASE__DISABLED)
43101 ? wuffs_base__error__disabled_by_previous_error
43102 : wuffs_base__error__initialize_not_called);
43103 }
43104 if (!a_dst || !a_src) {
43105 self->private_impl.magic = WUFFS_BASE__DISABLED;
43106 return wuffs_base__make_status(wuffs_base__error__bad_argument);
43107 }
43108 if ((self->private_impl.active_coroutine != 0) &&
43109 (self->private_impl.active_coroutine != 4)) {
43110 self->private_impl.magic = WUFFS_BASE__DISABLED;
43111 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
43112 }
43113 self->private_impl.active_coroutine = 0;
43114 wuffs_base__status status = wuffs_base__make_status(NULL);
43115
Nigel Taobf9dab32021-11-18 19:19:55 +110043116 uint8_t v_c = 0;
43117 uint16_t v_c2 = 0;
43118 wuffs_base__io_buffer u_w = wuffs_base__empty_io_buffer();
43119 wuffs_base__io_buffer* v_w = &u_w;
43120 uint8_t* iop_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43121 uint8_t* io0_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43122 uint8_t* io1_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43123 uint8_t* io2_v_w WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43124 uint64_t v_num_written = 0;
43125 uint64_t v_w_mark = 0;
43126 uint64_t v_r_mark = 0;
43127 wuffs_base__status v_zlib_status = wuffs_base__make_status(NULL);
Nigel Taoe360a532021-04-05 22:47:03 +100043128
Nigel Taobf9dab32021-11-18 19:19:55 +110043129 uint8_t* iop_a_dst = NULL;
43130 uint8_t* io0_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43131 uint8_t* io1_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43132 uint8_t* io2_a_dst WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110043133 if (a_dst && a_dst->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043134 io0_a_dst = a_dst->data.ptr;
43135 io1_a_dst = io0_a_dst + a_dst->meta.wi;
43136 iop_a_dst = io1_a_dst;
43137 io2_a_dst = io0_a_dst + a_dst->data.len;
43138 if (a_dst->meta.closed) {
43139 io2_a_dst = iop_a_dst;
43140 }
43141 }
43142 const uint8_t* iop_a_src = NULL;
43143 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43144 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
43145 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110043146 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043147 io0_a_src = a_src->data.ptr;
43148 io1_a_src = io0_a_src + a_src->meta.ri;
43149 iop_a_src = io1_a_src;
43150 io2_a_src = io0_a_src + a_src->meta.wi;
43151 }
43152
43153 uint32_t coro_susp_point = self->private_impl.p_tell_me_more[0];
43154 if (coro_susp_point) {
43155 v_zlib_status = self->private_data.s_tell_me_more[0].v_zlib_status;
43156 }
43157 switch (coro_susp_point) {
43158 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
43159
Nigel Tao123a5c62022-06-03 14:17:20 +100043160 if ((self->private_impl.f_call_sequence & 16) == 0) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043161 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
43162 goto exit;
43163 }
43164 if (self->private_impl.f_metadata_fourcc == 0) {
43165 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
43166 goto exit;
43167 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043168 while (true) {
43169 if (self->private_impl.f_metadata_flavor == 3) {
43170 while (true) {
43171 if (wuffs_base__u64__sat_add((a_src ? a_src->meta.pos : 0), ((uint64_t)(iop_a_src - io0_a_src))) != self->private_impl.f_metadata_y) {
43172 status = wuffs_base__make_status(wuffs_base__error__bad_i_o_position);
43173 goto exit;
43174 } else if (a_minfo != NULL) {
43175 wuffs_base__more_information__set(a_minfo,
43176 self->private_impl.f_metadata_flavor,
43177 self->private_impl.f_metadata_fourcc,
43178 self->private_impl.f_metadata_x,
43179 self->private_impl.f_metadata_y,
43180 self->private_impl.f_metadata_z);
43181 }
43182 if (self->private_impl.f_metadata_y >= self->private_impl.f_metadata_z) {
43183 goto label__goto_done__break;
43184 }
43185 self->private_impl.f_metadata_y = self->private_impl.f_metadata_z;
43186 status = wuffs_base__make_status(wuffs_base__suspension__even_more_information);
43187 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(1);
Nigel Taobf9dab32021-11-18 19:19:55 +110043188 }
43189 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043190 if (self->private_impl.f_metadata_is_zlib_compressed) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043191 if (self->private_impl.f_zlib_is_dirty) {
43192 wuffs_base__ignore_status(wuffs_zlib__decoder__initialize(&self->private_data.f_zlib,
43193 sizeof (wuffs_zlib__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED));
43194 if (self->private_impl.f_ignore_checksum) {
43195 wuffs_zlib__decoder__set_quirk_enabled(&self->private_data.f_zlib, 1, true);
43196 }
43197 }
43198 self->private_impl.f_zlib_is_dirty = true;
43199 self->private_impl.f_ztxt_hist_pos = 0;
43200 }
43201 label__loop__continue:;
43202 while (true) {
43203 if (a_minfo != NULL) {
43204 wuffs_base__more_information__set(a_minfo,
43205 self->private_impl.f_metadata_flavor,
43206 self->private_impl.f_metadata_fourcc,
43207 self->private_impl.f_metadata_x,
43208 self->private_impl.f_metadata_y,
43209 self->private_impl.f_metadata_z);
43210 }
43211 if (self->private_impl.f_metadata_flavor != 4) {
43212 goto label__loop__break;
43213 }
43214 if (self->private_impl.f_metadata_is_zlib_compressed) {
43215 if (self->private_impl.f_chunk_type == 1346585449) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043216 {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043217 const uint8_t *o_0_io2_a_src = io2_a_src;
43218 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
43219 ((uint64_t)(self->private_impl.f_chunk_length)));
Nigel Taobf9dab32021-11-18 19:19:55 +110043220 if (a_src) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043221 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
Nigel Taobf9dab32021-11-18 19:19:55 +110043222 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043223 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
Nigel Taobf9dab32021-11-18 19:19:55 +110043224 {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043225 if (a_dst) {
43226 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
Nigel Taobf9dab32021-11-18 19:19:55 +110043227 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043228 if (a_src) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043229 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
43230 }
43231 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());
43232 v_zlib_status = t_0;
43233 if (a_dst) {
43234 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
43235 }
43236 if (a_src) {
43237 iop_a_src = a_src->data.ptr + a_src->meta.ri;
Nigel Taobf9dab32021-11-18 19:19:55 +110043238 }
43239 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043240 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))));
43241 io2_a_src = o_0_io2_a_src;
43242 if (a_src) {
43243 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
43244 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043245 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043246 if (wuffs_base__status__is_ok(&v_zlib_status)) {
43247 self->private_impl.f_metadata_is_zlib_compressed = false;
43248 goto label__loop__break;
43249 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
43250 status = v_zlib_status;
43251 if (wuffs_base__status__is_error(&status)) {
43252 goto exit;
43253 } else if (wuffs_base__status__is_suspension(&status)) {
43254 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
43255 goto exit;
43256 }
43257 goto ok;
Nigel Taobf9dab32021-11-18 19:19:55 +110043258 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043259 status = v_zlib_status;
43260 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
43261 } else if (self->private_impl.f_chunk_type == 1951945833) {
43262 {
43263 const uint8_t *o_1_io2_a_src = io2_a_src;
43264 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
43265 ((uint64_t)(self->private_impl.f_chunk_length)));
43266 if (a_src) {
43267 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
43268 }
43269 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
43270 {
43271 if (a_dst) {
43272 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
43273 }
43274 if (a_src) {
43275 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
43276 }
43277 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());
43278 v_zlib_status = t_1;
43279 if (a_dst) {
43280 iop_a_dst = a_dst->data.ptr + a_dst->meta.wi;
43281 }
43282 if (a_src) {
43283 iop_a_src = a_src->data.ptr + a_src->meta.ri;
43284 }
43285 }
43286 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))));
43287 io2_a_src = o_1_io2_a_src;
43288 if (a_src) {
43289 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
43290 }
43291 }
43292 if (wuffs_base__status__is_ok(&v_zlib_status)) {
43293 self->private_impl.f_metadata_is_zlib_compressed = false;
43294 goto label__loop__break;
43295 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
43296 status = v_zlib_status;
43297 if (wuffs_base__status__is_error(&status)) {
43298 goto exit;
43299 } else if (wuffs_base__status__is_suspension(&status)) {
43300 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
43301 goto exit;
43302 }
43303 goto ok;
43304 }
43305 status = v_zlib_status;
43306 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
43307 } else if (self->private_impl.f_chunk_type == 1951945850) {
43308 if (self->private_impl.f_ztxt_ri == self->private_impl.f_ztxt_wi) {
43309 {
43310 wuffs_base__io_buffer* o_2_v_w = v_w;
43311 uint8_t *o_2_iop_v_w = iop_v_w;
43312 uint8_t *o_2_io0_v_w = io0_v_w;
43313 uint8_t *o_2_io1_v_w = io1_v_w;
43314 uint8_t *o_2_io2_v_w = io2_v_w;
43315 v_w = wuffs_base__io_writer__set(
43316 &u_w,
43317 &iop_v_w,
43318 &io0_v_w,
43319 &io1_v_w,
43320 &io2_v_w,
43321 wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024),
43322 self->private_impl.f_ztxt_hist_pos);
43323 {
43324 const uint8_t *o_3_io2_a_src = io2_a_src;
43325 wuffs_base__io_reader__limit(&io2_a_src, iop_a_src,
43326 ((uint64_t)(self->private_impl.f_chunk_length)));
43327 if (a_src) {
43328 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
43329 }
43330 v_w_mark = ((uint64_t)(iop_v_w - io0_v_w));
43331 v_r_mark = ((uint64_t)(iop_a_src - io0_a_src));
43332 {
43333 u_w.meta.wi = ((size_t)(iop_v_w - u_w.data.ptr));
43334 if (a_src) {
43335 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
43336 }
43337 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());
43338 v_zlib_status = t_2;
43339 iop_v_w = u_w.data.ptr + u_w.meta.wi;
43340 if (a_src) {
43341 iop_a_src = a_src->data.ptr + a_src->meta.ri;
43342 }
43343 }
43344 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))));
43345 v_num_written = wuffs_base__io__count_since(v_w_mark, ((uint64_t)(iop_v_w - io0_v_w)));
43346 io2_a_src = o_3_io2_a_src;
43347 if (a_src) {
43348 a_src->meta.wi = ((size_t)(io2_a_src - a_src->data.ptr));
43349 }
43350 }
43351 v_w = o_2_v_w;
43352 iop_v_w = o_2_iop_v_w;
43353 io0_v_w = o_2_io0_v_w;
43354 io1_v_w = o_2_io1_v_w;
43355 io2_v_w = o_2_io2_v_w;
43356 }
43357 if (v_num_written > 1024) {
43358 status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_i_o);
43359 goto exit;
43360 }
43361 self->private_impl.f_ztxt_ri = 0;
43362 self->private_impl.f_ztxt_wi = ((uint32_t)(v_num_written));
43363 wuffs_base__u64__sat_add_indirect(&self->private_impl.f_ztxt_hist_pos, v_num_written);
43364 }
43365 while (self->private_impl.f_ztxt_ri < self->private_impl.f_ztxt_wi) {
43366 v_c2 = WUFFS_PNG__LATIN_1[self->private_data.f_dst_palette[self->private_impl.f_ztxt_ri]];
43367 if (v_c2 == 0) {
43368 status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1);
43369 goto exit;
43370 } else if (v_c2 <= 127) {
43371 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
43372 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
43373 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
Nigel Taoebbecaa2022-01-08 14:08:27 +110043374 goto label__loop__continue;
43375 }
43376 self->private_impl.f_ztxt_ri += 1;
43377 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1);
43378 } else {
43379 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
43380 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
43381 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
Nigel Taoebbecaa2022-01-08 14:08:27 +110043382 goto label__loop__continue;
43383 }
43384 self->private_impl.f_ztxt_ri += 1;
43385 (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2);
43386 }
43387 }
43388 if (wuffs_base__status__is_ok(&v_zlib_status)) {
43389 self->private_impl.f_metadata_is_zlib_compressed = false;
43390 goto label__loop__break;
43391 } else if ( ! wuffs_base__status__is_suspension(&v_zlib_status)) {
43392 status = v_zlib_status;
43393 if (wuffs_base__status__is_error(&status)) {
43394 goto exit;
43395 } else if (wuffs_base__status__is_suspension(&status)) {
43396 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
43397 goto exit;
43398 }
43399 goto ok;
43400 } else if (v_zlib_status.repr != wuffs_base__suspension__short_write) {
43401 status = v_zlib_status;
43402 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
43403 }
43404 } else {
43405 status = wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_chunk_type);
43406 goto exit;
Nigel Taobf9dab32021-11-18 19:19:55 +110043407 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043408 } else if ((self->private_impl.f_chunk_type == 1951945833) && (self->private_impl.f_metadata_fourcc == 1263947862)) {
43409 while (true) {
43410 if (self->private_impl.f_chunk_length <= 0) {
43411 goto label__loop__break;
43412 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
43413 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43414 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
43415 goto label__loop__continue;
43416 } else if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
43417 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
43418 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
43419 goto label__loop__continue;
43420 }
43421 self->private_impl.f_chunk_length -= 1;
43422 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
43423 iop_a_src += 1;
43424 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, v_c), iop_a_dst += 1);
43425 }
43426 } else {
43427 while (true) {
43428 if (self->private_impl.f_chunk_length <= 0) {
43429 if (self->private_impl.f_metadata_fourcc == 1263947851) {
43430 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43431 goto exit;
43432 }
43433 goto label__loop__break;
43434 } else if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
43435 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43436 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
43437 goto label__loop__continue;
43438 }
43439 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
43440 if (v_c == 0) {
43441 self->private_impl.f_chunk_length -= 1;
43442 iop_a_src += 1;
43443 goto label__loop__break;
43444 }
43445 v_c2 = WUFFS_PNG__LATIN_1[v_c];
Nigel Taobf9dab32021-11-18 19:19:55 +110043446 if (v_c2 == 0) {
43447 status = wuffs_base__make_status(wuffs_png__error__bad_text_chunk_not_latin_1);
43448 goto exit;
43449 } else if (v_c2 <= 127) {
43450 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 0) {
43451 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
Nigel Taoebbecaa2022-01-08 14:08:27 +110043452 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
Nigel Taobf9dab32021-11-18 19:19:55 +110043453 goto label__loop__continue;
43454 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043455 self->private_impl.f_chunk_length -= 1;
43456 iop_a_src += 1;
Nigel Taobf9dab32021-11-18 19:19:55 +110043457 (wuffs_base__poke_u8be__no_bounds_check(iop_a_dst, ((uint8_t)(v_c2))), iop_a_dst += 1);
43458 } else {
43459 if (((uint64_t)(io2_a_dst - iop_a_dst)) <= 1) {
43460 status = wuffs_base__make_status(wuffs_base__suspension__short_write);
Nigel Taoebbecaa2022-01-08 14:08:27 +110043461 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11);
Nigel Taobf9dab32021-11-18 19:19:55 +110043462 goto label__loop__continue;
43463 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043464 self->private_impl.f_chunk_length -= 1;
43465 iop_a_src += 1;
Nigel Taobf9dab32021-11-18 19:19:55 +110043466 (wuffs_base__poke_u16le__no_bounds_check(iop_a_dst, v_c2), iop_a_dst += 2);
43467 }
43468 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043469 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043470 }
43471 label__loop__break:;
43472 if (self->private_impl.f_metadata_fourcc == 1263947851) {
43473 self->private_impl.f_metadata_fourcc = 1263947862;
43474 if (self->private_impl.f_chunk_type == 1951945833) {
43475 if (self->private_impl.f_chunk_length <= 1) {
43476 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43477 goto exit;
43478 }
43479 self->private_impl.f_chunk_length -= 2;
43480 {
43481 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
43482 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
43483 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43484 goto suspend;
43485 }
43486 uint8_t t_3 = *iop_a_src++;
43487 v_c = t_3;
43488 }
43489 if (v_c == 0) {
43490 self->private_impl.f_metadata_is_zlib_compressed = false;
43491 } else if (v_c == 1) {
43492 self->private_impl.f_metadata_is_zlib_compressed = true;
43493 } else {
43494 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43495 goto exit;
43496 }
43497 {
43498 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
43499 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
43500 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43501 goto suspend;
43502 }
43503 uint8_t t_4 = *iop_a_src++;
43504 v_c = t_4;
43505 }
43506 if ((v_c != 0) && self->private_impl.f_metadata_is_zlib_compressed) {
43507 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
43508 goto exit;
43509 }
43510 self->private_impl.f_metadata_fourcc -= 2;
43511 while (self->private_impl.f_metadata_fourcc != 1263947862) {
43512 self->private_impl.f_metadata_fourcc += 1;
43513 while (true) {
43514 if (self->private_impl.f_chunk_length <= 0) {
43515 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43516 goto exit;
43517 }
43518 self->private_impl.f_chunk_length -= 1;
43519 {
43520 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
43521 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
43522 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43523 goto suspend;
43524 }
43525 uint8_t t_5 = *iop_a_src++;
43526 v_c = t_5;
43527 }
43528 if (v_c == 0) {
43529 goto label__0__break;
43530 }
43531 }
43532 label__0__break:;
43533 }
43534 } else if (self->private_impl.f_chunk_type == 1951945850) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043535 if (self->private_impl.f_chunk_length <= 0) {
Nigel Taoebbecaa2022-01-08 14:08:27 +110043536 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43537 goto exit;
Nigel Taobf9dab32021-11-18 19:19:55 +110043538 }
43539 self->private_impl.f_chunk_length -= 1;
Nigel Taoebbecaa2022-01-08 14:08:27 +110043540 {
43541 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
43542 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
43543 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43544 goto suspend;
Nigel Taobf9dab32021-11-18 19:19:55 +110043545 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043546 uint8_t t_6 = *iop_a_src++;
43547 v_c = t_6;
Nigel Taobf9dab32021-11-18 19:19:55 +110043548 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043549 if (v_c != 0) {
43550 status = wuffs_base__make_status(wuffs_png__error__unsupported_png_compression_method);
Nigel Taobf9dab32021-11-18 19:19:55 +110043551 goto exit;
Nigel Taobf9dab32021-11-18 19:19:55 +110043552 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043553 self->private_impl.f_metadata_is_zlib_compressed = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110043554 }
Nigel Tao123a5c62022-06-03 14:17:20 +100043555 self->private_impl.f_call_sequence &= 239;
Nigel Taoebbecaa2022-01-08 14:08:27 +110043556 status = wuffs_base__make_status(NULL);
43557 goto ok;
Nigel Taobf9dab32021-11-18 19:19:55 +110043558 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043559 goto label__goto_done__break;
Nigel Taobf9dab32021-11-18 19:19:55 +110043560 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110043561 label__goto_done__break:;
43562 if (self->private_impl.f_chunk_length != 0) {
43563 status = wuffs_base__make_status(wuffs_png__error__bad_chunk);
43564 goto exit;
43565 }
43566 self->private_data.s_tell_me_more[0].scratch = 4;
43567 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
43568 if (self->private_data.s_tell_me_more[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
43569 self->private_data.s_tell_me_more[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
43570 iop_a_src = io2_a_src;
43571 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
43572 goto suspend;
43573 }
43574 iop_a_src += self->private_data.s_tell_me_more[0].scratch;
43575 self->private_impl.f_metadata_flavor = 0;
43576 self->private_impl.f_metadata_fourcc = 0;
43577 self->private_impl.f_metadata_x = 0;
43578 self->private_impl.f_metadata_y = 0;
43579 self->private_impl.f_metadata_z = 0;
Nigel Tao123a5c62022-06-03 14:17:20 +100043580 self->private_impl.f_call_sequence &= 239;
Nigel Taobf9dab32021-11-18 19:19:55 +110043581 status = wuffs_base__make_status(NULL);
43582 goto ok;
43583
43584 ok:
43585 self->private_impl.p_tell_me_more[0] = 0;
43586 goto exit;
43587 }
43588
43589 goto suspend;
43590 suspend:
43591 self->private_impl.p_tell_me_more[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
43592 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 4 : 0;
43593 self->private_data.s_tell_me_more[0].v_zlib_status = v_zlib_status;
43594
Nigel Taoe360a532021-04-05 22:47:03 +100043595 goto exit;
43596 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110043597 if (a_dst && a_dst->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043598 a_dst->meta.wi = ((size_t)(iop_a_dst - a_dst->data.ptr));
43599 }
Nigel Taoa0041ac2022-10-20 11:24:24 +110043600 if (a_src && a_src->data.ptr) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043601 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
43602 }
43603
Nigel Taoe360a532021-04-05 22:47:03 +100043604 if (wuffs_base__status__is_error(&status)) {
43605 self->private_impl.magic = WUFFS_BASE__DISABLED;
43606 }
43607 return status;
43608}
43609
43610// -------- func png.decoder.workbuf_len
43611
43612WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
43613wuffs_png__decoder__workbuf_len(
43614 const wuffs_png__decoder* self) {
43615 if (!self) {
43616 return wuffs_base__utility__empty_range_ii_u64();
43617 }
43618 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
43619 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
43620 return wuffs_base__utility__empty_range_ii_u64();
43621 }
43622
43623 return wuffs_base__utility__make_range_ii_u64(self->private_impl.f_overall_workbuf_length, self->private_impl.f_overall_workbuf_length);
43624}
43625
43626// -------- func png.decoder.filter_and_swizzle
43627
43628static wuffs_base__status
43629wuffs_png__decoder__filter_and_swizzle(
43630 wuffs_png__decoder* self,
43631 wuffs_base__pixel_buffer* a_dst,
43632 wuffs_base__slice_u8 a_workbuf) {
43633 return (*self->private_impl.choosy_filter_and_swizzle)(self, a_dst, a_workbuf);
43634}
43635
43636static wuffs_base__status
43637wuffs_png__decoder__filter_and_swizzle__choosy_default(
43638 wuffs_png__decoder* self,
43639 wuffs_base__pixel_buffer* a_dst,
43640 wuffs_base__slice_u8 a_workbuf) {
43641 wuffs_base__pixel_format v_dst_pixfmt = {0};
43642 uint32_t v_dst_bits_per_pixel = 0;
43643 uint64_t v_dst_bytes_per_pixel = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110043644 uint64_t v_dst_bytes_per_row0 = 0;
43645 uint64_t v_dst_bytes_per_row1 = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100043646 wuffs_base__slice_u8 v_dst_palette = {0};
43647 wuffs_base__table_u8 v_tab = {0};
43648 uint32_t v_y = 0;
43649 wuffs_base__slice_u8 v_dst = {0};
43650 uint8_t v_filter = 0;
43651 wuffs_base__slice_u8 v_curr_row = {0};
43652 wuffs_base__slice_u8 v_prev_row = {0};
43653
43654 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
43655 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
43656 if ((v_dst_bits_per_pixel & 7) != 0) {
43657 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
43658 }
43659 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
Nigel Taobf9dab32021-11-18 19:19:55 +110043660 v_dst_bytes_per_row0 = (((uint64_t)(self->private_impl.f_frame_rect_x0)) * v_dst_bytes_per_pixel);
43661 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 +100043662 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024));
43663 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
Nigel Taobf9dab32021-11-18 19:19:55 +110043664 if (v_dst_bytes_per_row1 < ((uint64_t)(v_tab.width))) {
43665 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
43666 0,
43667 0,
43668 v_dst_bytes_per_row1,
43669 ((uint64_t)(v_tab.height)));
43670 }
43671 if (v_dst_bytes_per_row0 < ((uint64_t)(v_tab.width))) {
43672 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
43673 v_dst_bytes_per_row0,
43674 0,
43675 ((uint64_t)(v_tab.width)),
43676 ((uint64_t)(v_tab.height)));
43677 } else {
43678 v_tab = wuffs_base__table_u8__subtable_ij(v_tab,
43679 0,
43680 0,
43681 0,
43682 0);
43683 }
43684 v_y = self->private_impl.f_frame_rect_y0;
43685 while (v_y < self->private_impl.f_frame_rect_y1) {
43686 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y);
Nigel Taoe360a532021-04-05 22:47:03 +100043687 if (1 > ((uint64_t)(a_workbuf.len))) {
43688 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
43689 }
43690 v_filter = a_workbuf.ptr[0];
43691 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1);
43692 if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) {
43693 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
43694 }
43695 v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row);
43696 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row);
43697 if (v_filter == 0) {
43698 } else if (v_filter == 1) {
43699 wuffs_png__decoder__filter_1(self, v_curr_row);
43700 } else if (v_filter == 2) {
43701 wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row);
43702 } else if (v_filter == 3) {
43703 wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row);
43704 } else if (v_filter == 4) {
43705 wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row);
43706 } else {
43707 return wuffs_base__make_status(wuffs_png__error__bad_filter);
43708 }
43709 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, v_curr_row);
43710 v_prev_row = v_curr_row;
43711 v_y += 1;
43712 }
43713 return wuffs_base__make_status(NULL);
43714}
43715
43716// -------- func png.decoder.filter_and_swizzle_tricky
43717
43718static wuffs_base__status
43719wuffs_png__decoder__filter_and_swizzle_tricky(
43720 wuffs_png__decoder* self,
43721 wuffs_base__pixel_buffer* a_dst,
43722 wuffs_base__slice_u8 a_workbuf) {
43723 wuffs_base__pixel_format v_dst_pixfmt = {0};
43724 uint32_t v_dst_bits_per_pixel = 0;
43725 uint64_t v_dst_bytes_per_pixel = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110043726 uint64_t v_dst_bytes_per_row1 = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100043727 wuffs_base__slice_u8 v_dst_palette = {0};
43728 wuffs_base__table_u8 v_tab = {0};
43729 uint64_t v_src_bytes_per_pixel = 0;
43730 uint32_t v_x = 0;
43731 uint32_t v_y = 0;
43732 uint64_t v_i = 0;
43733 wuffs_base__slice_u8 v_dst = {0};
43734 uint8_t v_filter = 0;
43735 wuffs_base__slice_u8 v_s = {0};
43736 wuffs_base__slice_u8 v_curr_row = {0};
43737 wuffs_base__slice_u8 v_prev_row = {0};
43738 uint8_t v_bits_unpacked[8] = {0};
43739 uint8_t v_bits_packed = 0;
43740 uint8_t v_packs_remaining = 0;
43741 uint8_t v_multiplier = 0;
43742 uint8_t v_shift = 0;
43743
43744 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
43745 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
43746 if ((v_dst_bits_per_pixel & 7) != 0) {
43747 return wuffs_base__make_status(wuffs_base__error__unsupported_option);
43748 }
43749 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
Nigel Taobf9dab32021-11-18 19:19:55 +110043750 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 +100043751 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024));
43752 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
43753 v_src_bytes_per_pixel = 1;
43754 if (self->private_impl.f_depth >= 8) {
43755 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))));
43756 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043757 if (self->private_impl.f_chunk_type_array[0] == 73) {
43758 v_y = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][5]));
43759 } else {
43760 v_y = self->private_impl.f_frame_rect_y0;
43761 }
43762 while (v_y < self->private_impl.f_frame_rect_y1) {
43763 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_y);
43764 if (v_dst_bytes_per_row1 < ((uint64_t)(v_dst.len))) {
43765 v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_dst_bytes_per_row1);
Nigel Taoe360a532021-04-05 22:47:03 +100043766 }
43767 if (1 > ((uint64_t)(a_workbuf.len))) {
43768 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
43769 }
43770 v_filter = a_workbuf.ptr[0];
43771 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, 1);
43772 if (self->private_impl.f_pass_bytes_per_row > ((uint64_t)(a_workbuf.len))) {
43773 return wuffs_base__make_status(wuffs_png__error__internal_error_inconsistent_workbuf_length);
43774 }
43775 v_curr_row = wuffs_base__slice_u8__subslice_j(a_workbuf, self->private_impl.f_pass_bytes_per_row);
43776 a_workbuf = wuffs_base__slice_u8__subslice_i(a_workbuf, self->private_impl.f_pass_bytes_per_row);
43777 if (v_filter == 0) {
43778 } else if (v_filter == 1) {
43779 wuffs_png__decoder__filter_1(self, v_curr_row);
43780 } else if (v_filter == 2) {
43781 wuffs_png__decoder__filter_2(self, v_curr_row, v_prev_row);
43782 } else if (v_filter == 3) {
43783 wuffs_png__decoder__filter_3(self, v_curr_row, v_prev_row);
43784 } else if (v_filter == 4) {
43785 wuffs_png__decoder__filter_4(self, v_curr_row, v_prev_row);
43786 } else {
43787 return wuffs_base__make_status(wuffs_png__error__bad_filter);
43788 }
43789 v_s = v_curr_row;
Nigel Taobf9dab32021-11-18 19:19:55 +110043790 if (self->private_impl.f_chunk_type_array[0] == 73) {
43791 v_x = ((uint32_t)(WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][2]));
43792 } else {
43793 v_x = self->private_impl.f_frame_rect_x0;
43794 }
Nigel Taoe360a532021-04-05 22:47:03 +100043795 if (self->private_impl.f_depth == 8) {
Nigel Taobf9dab32021-11-18 19:19:55 +110043796 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100043797 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
43798 if (v_i <= ((uint64_t)(v_dst.len))) {
43799 if (self->private_impl.f_color_type == 4) {
43800 if (2 <= ((uint64_t)(v_s.len))) {
43801 v_bits_unpacked[0] = v_s.ptr[0];
43802 v_bits_unpacked[1] = v_s.ptr[0];
43803 v_bits_unpacked[2] = v_s.ptr[0];
43804 v_bits_unpacked[3] = v_s.ptr[1];
43805 v_s = wuffs_base__slice_u8__subslice_i(v_s, 2);
43806 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));
43807 }
Nigel Taobf9dab32021-11-18 19:19:55 +110043808 } else if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) != 0) {
43809 if (self->private_impl.f_color_type == 0) {
43810 if (1 <= ((uint64_t)(v_s.len))) {
43811 v_bits_unpacked[0] = v_s.ptr[0];
43812 v_bits_unpacked[1] = v_s.ptr[0];
43813 v_bits_unpacked[2] = v_s.ptr[0];
43814 v_bits_unpacked[3] = 255;
43815 v_s = wuffs_base__slice_u8__subslice_i(v_s, 1);
43816 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
43817 (((uint32_t)(v_bits_unpacked[1])) << 8) |
43818 (((uint32_t)(v_bits_unpacked[2])) << 16) |
43819 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
43820 v_bits_unpacked[0] = 0;
43821 v_bits_unpacked[1] = 0;
43822 v_bits_unpacked[2] = 0;
43823 v_bits_unpacked[3] = 0;
43824 }
43825 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));
43826 }
43827 } else {
43828 if (3 <= ((uint64_t)(v_s.len))) {
43829 v_bits_unpacked[0] = v_s.ptr[2];
43830 v_bits_unpacked[1] = v_s.ptr[1];
43831 v_bits_unpacked[2] = v_s.ptr[0];
43832 v_bits_unpacked[3] = 255;
43833 v_s = wuffs_base__slice_u8__subslice_i(v_s, 3);
43834 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
43835 (((uint32_t)(v_bits_unpacked[1])) << 8) |
43836 (((uint32_t)(v_bits_unpacked[2])) << 16) |
43837 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
43838 v_bits_unpacked[0] = 0;
43839 v_bits_unpacked[1] = 0;
43840 v_bits_unpacked[2] = 0;
43841 v_bits_unpacked[3] = 0;
43842 }
43843 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));
43844 }
43845 }
Nigel Taoe360a532021-04-05 22:47:03 +100043846 } else if (v_src_bytes_per_pixel <= ((uint64_t)(v_s.len))) {
43847 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));
43848 v_s = wuffs_base__slice_u8__subslice_i(v_s, v_src_bytes_per_pixel);
43849 }
43850 }
43851 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
43852 }
43853 } else if (self->private_impl.f_depth < 8) {
43854 v_multiplier = 1;
43855 if (self->private_impl.f_color_type == 0) {
43856 v_multiplier = WUFFS_PNG__LOW_BIT_DEPTH_MULTIPLIERS[self->private_impl.f_depth];
43857 }
43858 v_shift = ((8 - self->private_impl.f_depth) & 7);
43859 v_packs_remaining = 0;
Nigel Taobf9dab32021-11-18 19:19:55 +110043860 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100043861 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
43862 if (v_i <= ((uint64_t)(v_dst.len))) {
43863 if ((v_packs_remaining == 0) && (1 <= ((uint64_t)(v_s.len)))) {
43864 v_packs_remaining = WUFFS_PNG__LOW_BIT_DEPTH_NUM_PACKS[self->private_impl.f_depth];
43865 v_bits_packed = v_s.ptr[0];
43866 v_s = wuffs_base__slice_u8__subslice_i(v_s, 1);
43867 }
43868 v_bits_unpacked[0] = ((uint8_t)((v_bits_packed >> v_shift) * v_multiplier));
43869 v_bits_packed = ((uint8_t)(v_bits_packed << self->private_impl.f_depth));
43870 v_packs_remaining = ((uint8_t)(v_packs_remaining - 1));
Nigel Taobf9dab32021-11-18 19:19:55 +110043871 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) != 0) {
43872 v_bits_unpacked[1] = v_bits_unpacked[0];
43873 v_bits_unpacked[2] = v_bits_unpacked[0];
43874 v_bits_unpacked[3] = 255;
43875 if (((uint32_t)((self->private_impl.f_remap_transparency & 4294967295))) == ((((uint32_t)(v_bits_unpacked[0])) << 0) |
43876 (((uint32_t)(v_bits_unpacked[1])) << 8) |
43877 (((uint32_t)(v_bits_unpacked[2])) << 16) |
43878 (((uint32_t)(v_bits_unpacked[3])) << 24))) {
43879 v_bits_unpacked[0] = 0;
43880 v_bits_unpacked[1] = 0;
43881 v_bits_unpacked[2] = 0;
43882 v_bits_unpacked[3] = 0;
43883 }
43884 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));
43885 } else {
43886 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));
43887 }
Nigel Taoe360a532021-04-05 22:47:03 +100043888 }
43889 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
43890 }
43891 } else {
Nigel Taobf9dab32021-11-18 19:19:55 +110043892 while (v_x < self->private_impl.f_frame_rect_x1) {
Nigel Taoe360a532021-04-05 22:47:03 +100043893 v_i = (((uint64_t)(v_x)) * v_dst_bytes_per_pixel);
43894 if (v_i <= ((uint64_t)(v_dst.len))) {
43895 if (self->private_impl.f_color_type == 0) {
43896 if (2 <= ((uint64_t)(v_s.len))) {
43897 v_bits_unpacked[0] = v_s.ptr[1];
43898 v_bits_unpacked[1] = v_s.ptr[0];
43899 v_bits_unpacked[2] = v_s.ptr[1];
43900 v_bits_unpacked[3] = v_s.ptr[0];
43901 v_bits_unpacked[4] = v_s.ptr[1];
43902 v_bits_unpacked[5] = v_s.ptr[0];
Nigel Taobf9dab32021-11-18 19:19:55 +110043903 v_bits_unpacked[6] = 255;
43904 v_bits_unpacked[7] = 255;
Nigel Taoe360a532021-04-05 22:47:03 +100043905 v_s = wuffs_base__slice_u8__subslice_i(v_s, 2);
Nigel Taobf9dab32021-11-18 19:19:55 +110043906 if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0])) << 0) |
43907 (((uint64_t)(v_bits_unpacked[1])) << 8) |
43908 (((uint64_t)(v_bits_unpacked[2])) << 16) |
43909 (((uint64_t)(v_bits_unpacked[3])) << 24) |
43910 (((uint64_t)(v_bits_unpacked[4])) << 32) |
43911 (((uint64_t)(v_bits_unpacked[5])) << 40) |
43912 (((uint64_t)(v_bits_unpacked[6])) << 48) |
43913 (((uint64_t)(v_bits_unpacked[7])) << 56))) {
43914 v_bits_unpacked[0] = 0;
43915 v_bits_unpacked[1] = 0;
43916 v_bits_unpacked[2] = 0;
43917 v_bits_unpacked[3] = 0;
43918 v_bits_unpacked[4] = 0;
43919 v_bits_unpacked[5] = 0;
43920 v_bits_unpacked[6] = 0;
43921 v_bits_unpacked[7] = 0;
43922 }
Nigel Taoe360a532021-04-05 22:47:03 +100043923 }
43924 } else if (self->private_impl.f_color_type == 2) {
43925 if (6 <= ((uint64_t)(v_s.len))) {
43926 v_bits_unpacked[0] = v_s.ptr[5];
43927 v_bits_unpacked[1] = v_s.ptr[4];
43928 v_bits_unpacked[2] = v_s.ptr[3];
43929 v_bits_unpacked[3] = v_s.ptr[2];
43930 v_bits_unpacked[4] = v_s.ptr[1];
43931 v_bits_unpacked[5] = v_s.ptr[0];
Nigel Taobf9dab32021-11-18 19:19:55 +110043932 v_bits_unpacked[6] = 255;
43933 v_bits_unpacked[7] = 255;
Nigel Taoe360a532021-04-05 22:47:03 +100043934 v_s = wuffs_base__slice_u8__subslice_i(v_s, 6);
Nigel Taobf9dab32021-11-18 19:19:55 +110043935 if (self->private_impl.f_remap_transparency == ((((uint64_t)(v_bits_unpacked[0])) << 0) |
43936 (((uint64_t)(v_bits_unpacked[1])) << 8) |
43937 (((uint64_t)(v_bits_unpacked[2])) << 16) |
43938 (((uint64_t)(v_bits_unpacked[3])) << 24) |
43939 (((uint64_t)(v_bits_unpacked[4])) << 32) |
43940 (((uint64_t)(v_bits_unpacked[5])) << 40) |
43941 (((uint64_t)(v_bits_unpacked[6])) << 48) |
43942 (((uint64_t)(v_bits_unpacked[7])) << 56))) {
43943 v_bits_unpacked[0] = 0;
43944 v_bits_unpacked[1] = 0;
43945 v_bits_unpacked[2] = 0;
43946 v_bits_unpacked[3] = 0;
43947 v_bits_unpacked[4] = 0;
43948 v_bits_unpacked[5] = 0;
43949 v_bits_unpacked[6] = 0;
43950 v_bits_unpacked[7] = 0;
43951 }
Nigel Taoe360a532021-04-05 22:47:03 +100043952 }
43953 } else if (self->private_impl.f_color_type == 4) {
43954 if (4 <= ((uint64_t)(v_s.len))) {
43955 v_bits_unpacked[0] = v_s.ptr[1];
43956 v_bits_unpacked[1] = v_s.ptr[0];
43957 v_bits_unpacked[2] = v_s.ptr[1];
43958 v_bits_unpacked[3] = v_s.ptr[0];
43959 v_bits_unpacked[4] = v_s.ptr[1];
43960 v_bits_unpacked[5] = v_s.ptr[0];
43961 v_bits_unpacked[6] = v_s.ptr[3];
43962 v_bits_unpacked[7] = v_s.ptr[2];
43963 v_s = wuffs_base__slice_u8__subslice_i(v_s, 4);
43964 }
43965 } else {
43966 if (8 <= ((uint64_t)(v_s.len))) {
43967 v_bits_unpacked[0] = v_s.ptr[5];
43968 v_bits_unpacked[1] = v_s.ptr[4];
43969 v_bits_unpacked[2] = v_s.ptr[3];
43970 v_bits_unpacked[3] = v_s.ptr[2];
43971 v_bits_unpacked[4] = v_s.ptr[1];
43972 v_bits_unpacked[5] = v_s.ptr[0];
43973 v_bits_unpacked[6] = v_s.ptr[7];
43974 v_bits_unpacked[7] = v_s.ptr[6];
43975 v_s = wuffs_base__slice_u8__subslice_i(v_s, 8);
43976 }
43977 }
43978 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));
43979 }
43980 v_x += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][0]);
43981 }
43982 }
43983 v_prev_row = v_curr_row;
43984 v_y += (((uint32_t)(1)) << WUFFS_PNG__INTERLACING[self->private_impl.f_interlace_pass][3]);
43985 }
43986 return wuffs_base__make_status(NULL);
43987}
43988
43989#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
43990
Nigel Taocc74cb42022-01-19 11:06:15 +110043991#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA)
43992
43993// ---------------- Status Codes Implementations
43994
43995const char wuffs_tga__error__bad_header[] = "#tga: bad header";
43996const char wuffs_tga__error__bad_run_length_encoding[] = "#tga: bad run length encoding";
43997const char wuffs_tga__error__unsupported_tga_file[] = "#tga: unsupported TGA file";
43998
43999// ---------------- Private Consts
44000
44001// ---------------- Private Initializer Prototypes
44002
44003// ---------------- Private Function Prototypes
44004
44005// ---------------- VTables
44006
44007const wuffs_base__image_decoder__func_ptrs
44008wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder = {
44009 (wuffs_base__status(*)(void*,
44010 wuffs_base__pixel_buffer*,
44011 wuffs_base__io_buffer*,
44012 wuffs_base__pixel_blend,
44013 wuffs_base__slice_u8,
44014 wuffs_base__decode_frame_options*))(&wuffs_tga__decoder__decode_frame),
44015 (wuffs_base__status(*)(void*,
44016 wuffs_base__frame_config*,
44017 wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_frame_config),
44018 (wuffs_base__status(*)(void*,
44019 wuffs_base__image_config*,
44020 wuffs_base__io_buffer*))(&wuffs_tga__decoder__decode_image_config),
44021 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_tga__decoder__frame_dirty_rect),
44022 (uint32_t(*)(const void*))(&wuffs_tga__decoder__num_animation_loops),
44023 (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frame_configs),
44024 (uint64_t(*)(const void*))(&wuffs_tga__decoder__num_decoded_frames),
44025 (wuffs_base__status(*)(void*,
44026 uint64_t,
44027 uint64_t))(&wuffs_tga__decoder__restart_frame),
44028 (wuffs_base__empty_struct(*)(void*,
44029 uint32_t,
44030 bool))(&wuffs_tga__decoder__set_quirk_enabled),
44031 (wuffs_base__empty_struct(*)(void*,
44032 uint32_t,
44033 bool))(&wuffs_tga__decoder__set_report_metadata),
44034 (wuffs_base__status(*)(void*,
44035 wuffs_base__io_buffer*,
44036 wuffs_base__more_information*,
44037 wuffs_base__io_buffer*))(&wuffs_tga__decoder__tell_me_more),
44038 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_tga__decoder__workbuf_len),
44039};
44040
44041// ---------------- Initializer Implementations
44042
44043wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
44044wuffs_tga__decoder__initialize(
44045 wuffs_tga__decoder* self,
44046 size_t sizeof_star_self,
44047 uint64_t wuffs_version,
44048 uint32_t options){
44049 if (!self) {
44050 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
44051 }
44052 if (sizeof(*self) != sizeof_star_self) {
44053 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
44054 }
44055 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
44056 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
44057 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
44058 }
44059
44060 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
44061 // The whole point of this if-check is to detect an uninitialized *self.
44062 // We disable the warning on GCC. Clang-5.0 does not have this warning.
44063#if !defined(__clang__) && defined(__GNUC__)
44064#pragma GCC diagnostic push
44065#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
44066#endif
44067 if (self->private_impl.magic != 0) {
44068 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
44069 }
44070#if !defined(__clang__) && defined(__GNUC__)
44071#pragma GCC diagnostic pop
44072#endif
44073 } else {
44074 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
44075 memset(self, 0, sizeof(*self));
44076 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
44077 } else {
44078 memset(&(self->private_impl), 0, sizeof(self->private_impl));
44079 }
44080 }
44081
44082 self->private_impl.magic = WUFFS_BASE__MAGIC;
44083 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
44084 wuffs_base__image_decoder__vtable_name;
44085 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
44086 (const void*)(&wuffs_tga__decoder__func_ptrs_for__wuffs_base__image_decoder);
44087 return wuffs_base__make_status(NULL);
44088}
44089
44090wuffs_tga__decoder*
44091wuffs_tga__decoder__alloc() {
44092 wuffs_tga__decoder* x =
44093 (wuffs_tga__decoder*)(calloc(sizeof(wuffs_tga__decoder), 1));
44094 if (!x) {
44095 return NULL;
44096 }
44097 if (wuffs_tga__decoder__initialize(
44098 x, sizeof(wuffs_tga__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
44099 free(x);
44100 return NULL;
44101 }
44102 return x;
44103}
44104
44105size_t
44106sizeof__wuffs_tga__decoder() {
44107 return sizeof(wuffs_tga__decoder);
44108}
44109
44110// ---------------- Function Implementations
44111
44112// -------- func tga.decoder.set_quirk_enabled
44113
44114WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
44115wuffs_tga__decoder__set_quirk_enabled(
44116 wuffs_tga__decoder* self,
44117 uint32_t a_quirk,
44118 bool a_enabled) {
44119 return wuffs_base__make_empty_struct();
44120}
44121
44122// -------- func tga.decoder.decode_image_config
44123
44124WUFFS_BASE__MAYBE_STATIC wuffs_base__status
44125wuffs_tga__decoder__decode_image_config(
44126 wuffs_tga__decoder* self,
44127 wuffs_base__image_config* a_dst,
44128 wuffs_base__io_buffer* a_src) {
44129 if (!self) {
44130 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
44131 }
44132 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
44133 return wuffs_base__make_status(
44134 (self->private_impl.magic == WUFFS_BASE__DISABLED)
44135 ? wuffs_base__error__disabled_by_previous_error
44136 : wuffs_base__error__initialize_not_called);
44137 }
44138 if (!a_src) {
44139 self->private_impl.magic = WUFFS_BASE__DISABLED;
44140 return wuffs_base__make_status(wuffs_base__error__bad_argument);
44141 }
44142 if ((self->private_impl.active_coroutine != 0) &&
44143 (self->private_impl.active_coroutine != 1)) {
44144 self->private_impl.magic = WUFFS_BASE__DISABLED;
44145 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
44146 }
44147 self->private_impl.active_coroutine = 0;
44148 wuffs_base__status status = wuffs_base__make_status(NULL);
44149
44150 uint32_t v_c = 0;
44151 uint32_t v_c5 = 0;
44152 uint32_t v_i = 0;
44153
44154 const uint8_t* iop_a_src = NULL;
44155 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44156 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44157 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110044158 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044159 io0_a_src = a_src->data.ptr;
44160 io1_a_src = io0_a_src + a_src->meta.ri;
44161 iop_a_src = io1_a_src;
44162 io2_a_src = io0_a_src + a_src->meta.wi;
44163 }
44164
44165 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
44166 if (coro_susp_point) {
44167 v_i = self->private_data.s_decode_image_config[0].v_i;
44168 }
44169 switch (coro_susp_point) {
44170 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
44171
44172 if (self->private_impl.f_call_sequence != 0) {
44173 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
44174 goto exit;
44175 }
44176 {
44177 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
44178 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44179 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44180 goto suspend;
44181 }
44182 uint8_t t_0 = *iop_a_src++;
44183 self->private_impl.f_header_id_length = t_0;
44184 }
44185 {
44186 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
44187 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44188 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44189 goto suspend;
44190 }
44191 uint8_t t_1 = *iop_a_src++;
44192 self->private_impl.f_header_color_map_type = t_1;
44193 }
44194 if (self->private_impl.f_header_color_map_type > 1) {
44195 status = wuffs_base__make_status(wuffs_tga__error__bad_header);
44196 goto exit;
44197 }
44198 {
44199 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(3);
44200 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44201 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44202 goto suspend;
44203 }
44204 uint8_t t_2 = *iop_a_src++;
44205 self->private_impl.f_header_image_type = t_2;
44206 }
44207 if ((self->private_impl.f_header_image_type == 1) ||
44208 (self->private_impl.f_header_image_type == 2) ||
44209 (self->private_impl.f_header_image_type == 3) ||
44210 (self->private_impl.f_header_image_type == 9) ||
44211 (self->private_impl.f_header_image_type == 10) ||
44212 (self->private_impl.f_header_image_type == 11)) {
44213 } else {
44214 status = wuffs_base__make_status(wuffs_tga__error__bad_header);
44215 goto exit;
44216 }
44217 {
44218 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(4);
44219 uint16_t t_3;
44220 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
44221 t_3 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
44222 iop_a_src += 2;
44223 } else {
44224 self->private_data.s_decode_image_config[0].scratch = 0;
44225 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(5);
44226 while (true) {
44227 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44228 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44229 goto suspend;
44230 }
44231 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44232 uint32_t num_bits_3 = ((uint32_t)(*scratch >> 56));
44233 *scratch <<= 8;
44234 *scratch >>= 8;
44235 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_3;
44236 if (num_bits_3 == 8) {
44237 t_3 = ((uint16_t)(*scratch));
44238 break;
44239 }
44240 num_bits_3 += 8;
44241 *scratch |= ((uint64_t)(num_bits_3)) << 56;
44242 }
44243 }
44244 self->private_impl.f_header_color_map_first_entry_index = t_3;
44245 }
44246 {
44247 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
44248 uint16_t t_4;
44249 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
44250 t_4 = wuffs_base__peek_u16le__no_bounds_check(iop_a_src);
44251 iop_a_src += 2;
44252 } else {
44253 self->private_data.s_decode_image_config[0].scratch = 0;
44254 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
44255 while (true) {
44256 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44257 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44258 goto suspend;
44259 }
44260 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44261 uint32_t num_bits_4 = ((uint32_t)(*scratch >> 56));
44262 *scratch <<= 8;
44263 *scratch >>= 8;
44264 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_4;
44265 if (num_bits_4 == 8) {
44266 t_4 = ((uint16_t)(*scratch));
44267 break;
44268 }
44269 num_bits_4 += 8;
44270 *scratch |= ((uint64_t)(num_bits_4)) << 56;
44271 }
44272 }
44273 self->private_impl.f_header_color_map_length = t_4;
44274 }
44275 {
44276 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
44277 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44278 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44279 goto suspend;
44280 }
44281 uint8_t t_5 = *iop_a_src++;
44282 self->private_impl.f_header_color_map_entry_size = t_5;
44283 }
44284 if (self->private_impl.f_header_color_map_type != 0) {
44285 if ((self->private_impl.f_header_color_map_first_entry_index != 0) || (self->private_impl.f_header_color_map_length > 256)) {
44286 status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file);
44287 goto exit;
44288 } else if ((self->private_impl.f_header_color_map_entry_size != 15) &&
44289 (self->private_impl.f_header_color_map_entry_size != 16) &&
44290 (self->private_impl.f_header_color_map_entry_size != 24) &&
44291 (self->private_impl.f_header_color_map_entry_size != 32)) {
44292 status = wuffs_base__make_status(wuffs_tga__error__bad_header);
44293 goto exit;
44294 }
44295 } else {
44296 if ((self->private_impl.f_header_color_map_first_entry_index != 0) || (self->private_impl.f_header_color_map_length != 0) || (self->private_impl.f_header_color_map_entry_size != 0)) {
44297 status = wuffs_base__make_status(wuffs_tga__error__bad_header);
44298 goto exit;
44299 }
44300 }
44301 self->private_data.s_decode_image_config[0].scratch = 4;
44302 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
44303 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
44304 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
44305 iop_a_src = io2_a_src;
44306 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44307 goto suspend;
44308 }
44309 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
44310 {
44311 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(10);
44312 uint32_t t_6;
44313 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
44314 t_6 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
44315 iop_a_src += 2;
44316 } else {
44317 self->private_data.s_decode_image_config[0].scratch = 0;
44318 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(11);
44319 while (true) {
44320 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44321 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44322 goto suspend;
44323 }
44324 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44325 uint32_t num_bits_6 = ((uint32_t)(*scratch >> 56));
44326 *scratch <<= 8;
44327 *scratch >>= 8;
44328 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_6;
44329 if (num_bits_6 == 8) {
44330 t_6 = ((uint32_t)(*scratch));
44331 break;
44332 }
44333 num_bits_6 += 8;
44334 *scratch |= ((uint64_t)(num_bits_6)) << 56;
44335 }
44336 }
44337 self->private_impl.f_width = t_6;
44338 }
44339 {
44340 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(12);
44341 uint32_t t_7;
44342 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
44343 t_7 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
44344 iop_a_src += 2;
44345 } else {
44346 self->private_data.s_decode_image_config[0].scratch = 0;
44347 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(13);
44348 while (true) {
44349 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44350 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44351 goto suspend;
44352 }
44353 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44354 uint32_t num_bits_7 = ((uint32_t)(*scratch >> 56));
44355 *scratch <<= 8;
44356 *scratch >>= 8;
44357 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_7;
44358 if (num_bits_7 == 8) {
44359 t_7 = ((uint32_t)(*scratch));
44360 break;
44361 }
44362 num_bits_7 += 8;
44363 *scratch |= ((uint64_t)(num_bits_7)) << 56;
44364 }
44365 }
44366 self->private_impl.f_height = t_7;
44367 }
44368 {
44369 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(14);
44370 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44371 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44372 goto suspend;
44373 }
44374 uint8_t t_8 = *iop_a_src++;
44375 self->private_impl.f_header_pixel_depth = t_8;
44376 }
44377 if ((self->private_impl.f_header_pixel_depth != 1) &&
44378 (self->private_impl.f_header_pixel_depth != 8) &&
44379 (self->private_impl.f_header_pixel_depth != 15) &&
44380 (self->private_impl.f_header_pixel_depth != 16) &&
44381 (self->private_impl.f_header_pixel_depth != 24) &&
44382 (self->private_impl.f_header_pixel_depth != 32)) {
44383 status = wuffs_base__make_status(wuffs_tga__error__bad_header);
44384 goto exit;
44385 }
44386 if ((self->private_impl.f_header_image_type | 8) == 9) {
44387 self->private_impl.f_scratch_bytes_per_pixel = 1;
44388 self->private_impl.f_src_bytes_per_pixel = 1;
44389 self->private_impl.f_src_pixfmt = 2164523016;
44390 self->private_impl.f_opaque = ((self->private_impl.f_header_color_map_entry_size == 15) || (self->private_impl.f_header_color_map_entry_size == 24));
44391 } else if ((self->private_impl.f_header_image_type | 8) == 10) {
44392 if ((self->private_impl.f_header_pixel_depth == 15) || (self->private_impl.f_header_pixel_depth == 16)) {
44393 self->private_impl.f_scratch_bytes_per_pixel = 4;
44394 self->private_impl.f_src_bytes_per_pixel = 0;
44395 self->private_impl.f_src_pixfmt = 2164295816;
44396 } else if (self->private_impl.f_header_pixel_depth == 24) {
44397 self->private_impl.f_scratch_bytes_per_pixel = 3;
44398 self->private_impl.f_src_bytes_per_pixel = 3;
44399 self->private_impl.f_src_pixfmt = 2147485832;
44400 self->private_impl.f_opaque = true;
44401 } else if (self->private_impl.f_header_pixel_depth == 32) {
44402 self->private_impl.f_scratch_bytes_per_pixel = 4;
44403 self->private_impl.f_src_bytes_per_pixel = 4;
44404 self->private_impl.f_src_pixfmt = 2164295816;
44405 } else {
44406 status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file);
44407 goto exit;
44408 }
44409 } else {
44410 if (self->private_impl.f_header_pixel_depth == 8) {
44411 self->private_impl.f_scratch_bytes_per_pixel = 1;
44412 self->private_impl.f_src_bytes_per_pixel = 1;
44413 self->private_impl.f_src_pixfmt = 536870920;
44414 self->private_impl.f_opaque = true;
44415 } else {
44416 status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file);
44417 goto exit;
44418 }
44419 }
44420 {
44421 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(15);
44422 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44423 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44424 goto suspend;
44425 }
44426 uint8_t t_9 = *iop_a_src++;
44427 self->private_impl.f_header_image_descriptor = t_9;
44428 }
44429 if ((self->private_impl.f_header_image_descriptor & 16) != 0) {
44430 status = wuffs_base__make_status(wuffs_tga__error__unsupported_tga_file);
44431 goto exit;
44432 }
44433 self->private_data.s_decode_image_config[0].scratch = ((uint32_t)(self->private_impl.f_header_id_length));
44434 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(16);
44435 if (self->private_data.s_decode_image_config[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
44436 self->private_data.s_decode_image_config[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
44437 iop_a_src = io2_a_src;
44438 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44439 goto suspend;
44440 }
44441 iop_a_src += self->private_data.s_decode_image_config[0].scratch;
44442 if (self->private_impl.f_header_color_map_type != 0) {
44443 while (v_i < ((uint32_t)(self->private_impl.f_header_color_map_length))) {
44444 if (self->private_impl.f_header_color_map_entry_size == 24) {
44445 {
44446 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(17);
44447 uint32_t t_10;
44448 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 3)) {
44449 t_10 = ((uint32_t)(wuffs_base__peek_u24le__no_bounds_check(iop_a_src)));
44450 iop_a_src += 3;
44451 } else {
44452 self->private_data.s_decode_image_config[0].scratch = 0;
44453 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(18);
44454 while (true) {
44455 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44456 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44457 goto suspend;
44458 }
44459 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44460 uint32_t num_bits_10 = ((uint32_t)(*scratch >> 56));
44461 *scratch <<= 8;
44462 *scratch >>= 8;
44463 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_10;
44464 if (num_bits_10 == 16) {
44465 t_10 = ((uint32_t)(*scratch));
44466 break;
44467 }
44468 num_bits_10 += 8;
44469 *scratch |= ((uint64_t)(num_bits_10)) << 56;
44470 }
44471 }
44472 v_c = t_10;
44473 }
44474 self->private_data.f_src_palette[(((v_i & 255) * 4) + 0)] = ((uint8_t)(((v_c >> 0) & 255)));
44475 self->private_data.f_src_palette[(((v_i & 255) * 4) + 1)] = ((uint8_t)(((v_c >> 8) & 255)));
44476 self->private_data.f_src_palette[(((v_i & 255) * 4) + 2)] = ((uint8_t)(((v_c >> 16) & 255)));
44477 self->private_data.f_src_palette[(((v_i & 255) * 4) + 3)] = 255;
44478 } else if (self->private_impl.f_header_color_map_entry_size == 32) {
44479 {
44480 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(19);
44481 uint32_t t_11;
44482 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 4)) {
44483 t_11 = wuffs_base__peek_u32le__no_bounds_check(iop_a_src);
44484 iop_a_src += 4;
44485 } else {
44486 self->private_data.s_decode_image_config[0].scratch = 0;
44487 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(20);
44488 while (true) {
44489 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44490 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44491 goto suspend;
44492 }
44493 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44494 uint32_t num_bits_11 = ((uint32_t)(*scratch >> 56));
44495 *scratch <<= 8;
44496 *scratch >>= 8;
44497 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_11;
44498 if (num_bits_11 == 24) {
44499 t_11 = ((uint32_t)(*scratch));
44500 break;
44501 }
44502 num_bits_11 += 8;
44503 *scratch |= ((uint64_t)(num_bits_11)) << 56;
44504 }
44505 }
44506 v_c = t_11;
44507 }
44508 self->private_data.f_src_palette[(((v_i & 255) * 4) + 0)] = ((uint8_t)(((v_c >> 0) & 255)));
44509 self->private_data.f_src_palette[(((v_i & 255) * 4) + 1)] = ((uint8_t)(((v_c >> 8) & 255)));
44510 self->private_data.f_src_palette[(((v_i & 255) * 4) + 2)] = ((uint8_t)(((v_c >> 16) & 255)));
44511 self->private_data.f_src_palette[(((v_i & 255) * 4) + 3)] = ((uint8_t)(((v_c >> 24) & 255)));
44512 } else {
44513 {
44514 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(21);
44515 uint32_t t_12;
44516 if (WUFFS_BASE__LIKELY(io2_a_src - iop_a_src >= 2)) {
44517 t_12 = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
44518 iop_a_src += 2;
44519 } else {
44520 self->private_data.s_decode_image_config[0].scratch = 0;
44521 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(22);
44522 while (true) {
44523 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
44524 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44525 goto suspend;
44526 }
44527 uint64_t* scratch = &self->private_data.s_decode_image_config[0].scratch;
44528 uint32_t num_bits_12 = ((uint32_t)(*scratch >> 56));
44529 *scratch <<= 8;
44530 *scratch >>= 8;
44531 *scratch |= ((uint64_t)(*iop_a_src++)) << num_bits_12;
44532 if (num_bits_12 == 8) {
44533 t_12 = ((uint32_t)(*scratch));
44534 break;
44535 }
44536 num_bits_12 += 8;
44537 *scratch |= ((uint64_t)(num_bits_12)) << 56;
44538 }
44539 }
44540 v_c = t_12;
44541 }
44542 v_c5 = (31 & (v_c >> 0));
44543 self->private_data.f_src_palette[(((v_i & 255) * 4) + 0)] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44544 v_c5 = (31 & (v_c >> 5));
44545 self->private_data.f_src_palette[(((v_i & 255) * 4) + 1)] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44546 v_c5 = (31 & (v_c >> 10));
44547 self->private_data.f_src_palette[(((v_i & 255) * 4) + 2)] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44548 self->private_data.f_src_palette[(((v_i & 255) * 4) + 3)] = 255;
44549 }
44550 v_i += 1;
44551 }
44552 while (v_i < 256) {
44553 self->private_data.f_src_palette[((v_i * 4) + 0)] = 0;
44554 self->private_data.f_src_palette[((v_i * 4) + 1)] = 0;
44555 self->private_data.f_src_palette[((v_i * 4) + 2)] = 0;
44556 self->private_data.f_src_palette[((v_i * 4) + 3)] = 255;
44557 v_i += 1;
44558 }
44559 }
44560 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)));
44561 if (a_dst != NULL) {
44562 wuffs_base__image_config__set(
44563 a_dst,
44564 self->private_impl.f_src_pixfmt,
44565 0,
44566 self->private_impl.f_width,
44567 self->private_impl.f_height,
44568 self->private_impl.f_frame_config_io_position,
44569 self->private_impl.f_opaque);
44570 }
Nigel Tao123a5c62022-06-03 14:17:20 +100044571 self->private_impl.f_call_sequence = 32;
Nigel Taocc74cb42022-01-19 11:06:15 +110044572
44573 goto ok;
44574 ok:
44575 self->private_impl.p_decode_image_config[0] = 0;
44576 goto exit;
44577 }
44578
44579 goto suspend;
44580 suspend:
44581 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
44582 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
44583 self->private_data.s_decode_image_config[0].v_i = v_i;
44584
44585 goto exit;
44586 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110044587 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044588 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
44589 }
44590
44591 if (wuffs_base__status__is_error(&status)) {
44592 self->private_impl.magic = WUFFS_BASE__DISABLED;
44593 }
44594 return status;
44595}
44596
44597// -------- func tga.decoder.decode_frame_config
44598
44599WUFFS_BASE__MAYBE_STATIC wuffs_base__status
44600wuffs_tga__decoder__decode_frame_config(
44601 wuffs_tga__decoder* self,
44602 wuffs_base__frame_config* a_dst,
44603 wuffs_base__io_buffer* a_src) {
44604 if (!self) {
44605 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
44606 }
44607 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
44608 return wuffs_base__make_status(
44609 (self->private_impl.magic == WUFFS_BASE__DISABLED)
44610 ? wuffs_base__error__disabled_by_previous_error
44611 : wuffs_base__error__initialize_not_called);
44612 }
44613 if (!a_src) {
44614 self->private_impl.magic = WUFFS_BASE__DISABLED;
44615 return wuffs_base__make_status(wuffs_base__error__bad_argument);
44616 }
44617 if ((self->private_impl.active_coroutine != 0) &&
44618 (self->private_impl.active_coroutine != 2)) {
44619 self->private_impl.magic = WUFFS_BASE__DISABLED;
44620 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
44621 }
44622 self->private_impl.active_coroutine = 0;
44623 wuffs_base__status status = wuffs_base__make_status(NULL);
44624
44625 const uint8_t* iop_a_src = NULL;
44626 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44627 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44628 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110044629 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044630 io0_a_src = a_src->data.ptr;
44631 io1_a_src = io0_a_src + a_src->meta.ri;
44632 iop_a_src = io1_a_src;
44633 io2_a_src = io0_a_src + a_src->meta.wi;
44634 }
44635
44636 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
44637 switch (coro_susp_point) {
44638 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
44639
Nigel Tao123a5c62022-06-03 14:17:20 +100044640 if (self->private_impl.f_call_sequence == 32) {
44641 } else if (self->private_impl.f_call_sequence < 32) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044642 if (a_src) {
44643 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
44644 }
44645 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
44646 status = wuffs_tga__decoder__decode_image_config(self, NULL, a_src);
44647 if (a_src) {
44648 iop_a_src = a_src->data.ptr + a_src->meta.ri;
44649 }
44650 if (status.repr) {
44651 goto suspend;
44652 }
Nigel Tao123a5c62022-06-03 14:17:20 +100044653 } else if (self->private_impl.f_call_sequence == 40) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044654 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)))) {
44655 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
44656 goto exit;
44657 }
Nigel Tao123a5c62022-06-03 14:17:20 +100044658 } else if (self->private_impl.f_call_sequence == 64) {
44659 self->private_impl.f_call_sequence = 96;
Nigel Taocc74cb42022-01-19 11:06:15 +110044660 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
44661 goto ok;
44662 } else {
44663 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
44664 goto ok;
44665 }
44666 if (a_dst != NULL) {
44667 wuffs_base__frame_config__set(
44668 a_dst,
44669 wuffs_base__utility__make_rect_ie_u32(
44670 0,
44671 0,
44672 self->private_impl.f_width,
44673 self->private_impl.f_height),
44674 ((wuffs_base__flicks)(0)),
44675 0,
44676 self->private_impl.f_frame_config_io_position,
44677 0,
44678 self->private_impl.f_opaque,
44679 false,
44680 4278190080);
44681 }
Nigel Tao123a5c62022-06-03 14:17:20 +100044682 self->private_impl.f_call_sequence = 64;
Nigel Taocc74cb42022-01-19 11:06:15 +110044683
44684 ok:
44685 self->private_impl.p_decode_frame_config[0] = 0;
44686 goto exit;
44687 }
44688
44689 goto suspend;
44690 suspend:
44691 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
44692 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
44693
44694 goto exit;
44695 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110044696 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044697 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
44698 }
44699
44700 if (wuffs_base__status__is_error(&status)) {
44701 self->private_impl.magic = WUFFS_BASE__DISABLED;
44702 }
44703 return status;
44704}
44705
44706// -------- func tga.decoder.decode_frame
44707
44708WUFFS_BASE__MAYBE_STATIC wuffs_base__status
44709wuffs_tga__decoder__decode_frame(
44710 wuffs_tga__decoder* self,
44711 wuffs_base__pixel_buffer* a_dst,
44712 wuffs_base__io_buffer* a_src,
44713 wuffs_base__pixel_blend a_blend,
44714 wuffs_base__slice_u8 a_workbuf,
44715 wuffs_base__decode_frame_options* a_opts) {
44716 if (!self) {
44717 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
44718 }
44719 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
44720 return wuffs_base__make_status(
44721 (self->private_impl.magic == WUFFS_BASE__DISABLED)
44722 ? wuffs_base__error__disabled_by_previous_error
44723 : wuffs_base__error__initialize_not_called);
44724 }
44725 if (!a_dst || !a_src) {
44726 self->private_impl.magic = WUFFS_BASE__DISABLED;
44727 return wuffs_base__make_status(wuffs_base__error__bad_argument);
44728 }
44729 if ((self->private_impl.active_coroutine != 0) &&
44730 (self->private_impl.active_coroutine != 3)) {
44731 self->private_impl.magic = WUFFS_BASE__DISABLED;
44732 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
44733 }
44734 self->private_impl.active_coroutine = 0;
44735 wuffs_base__status status = wuffs_base__make_status(NULL);
44736
44737 wuffs_base__status v_status = wuffs_base__make_status(NULL);
44738 wuffs_base__pixel_format v_dst_pixfmt = {0};
44739 uint32_t v_dst_bits_per_pixel = 0;
44740 uint64_t v_dst_bytes_per_pixel = 0;
44741 uint32_t v_dst_x = 0;
44742 uint32_t v_dst_y = 0;
44743 wuffs_base__table_u8 v_tab = {0};
44744 wuffs_base__slice_u8 v_dst_palette = {0};
44745 wuffs_base__slice_u8 v_dst = {0};
44746 uint64_t v_dst_start = 0;
44747 wuffs_base__slice_u8 v_src_palette = {0};
44748 uint64_t v_mark = 0;
44749 uint64_t v_num_pixels64 = 0;
44750 uint32_t v_num_pixels32 = 0;
44751 uint32_t v_lit_length = 0;
44752 uint32_t v_run_length = 0;
44753 uint64_t v_num_dst_bytes = 0;
44754 uint32_t v_num_src_bytes = 0;
44755 uint32_t v_c = 0;
44756 uint32_t v_c5 = 0;
44757
44758 const uint8_t* iop_a_src = NULL;
44759 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44760 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
44761 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110044762 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044763 io0_a_src = a_src->data.ptr;
44764 io1_a_src = io0_a_src + a_src->meta.ri;
44765 iop_a_src = io1_a_src;
44766 io2_a_src = io0_a_src + a_src->meta.wi;
44767 }
44768
44769 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
44770 if (coro_susp_point) {
44771 v_dst_bytes_per_pixel = self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel;
44772 v_dst_x = self->private_data.s_decode_frame[0].v_dst_x;
44773 v_dst_y = self->private_data.s_decode_frame[0].v_dst_y;
44774 v_mark = self->private_data.s_decode_frame[0].v_mark;
44775 v_num_pixels32 = self->private_data.s_decode_frame[0].v_num_pixels32;
44776 v_lit_length = self->private_data.s_decode_frame[0].v_lit_length;
44777 v_run_length = self->private_data.s_decode_frame[0].v_run_length;
44778 v_num_dst_bytes = self->private_data.s_decode_frame[0].v_num_dst_bytes;
44779 }
44780 switch (coro_susp_point) {
44781 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
44782
Nigel Tao123a5c62022-06-03 14:17:20 +100044783 if (self->private_impl.f_call_sequence == 64) {
44784 } else if (self->private_impl.f_call_sequence < 64) {
Nigel Taocc74cb42022-01-19 11:06:15 +110044785 if (a_src) {
44786 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
44787 }
44788 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
44789 status = wuffs_tga__decoder__decode_frame_config(self, NULL, a_src);
44790 if (a_src) {
44791 iop_a_src = a_src->data.ptr + a_src->meta.ri;
44792 }
44793 if (status.repr) {
44794 goto suspend;
44795 }
Nigel Taocc74cb42022-01-19 11:06:15 +110044796 } else {
44797 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
44798 goto ok;
44799 }
44800 if (self->private_impl.f_header_color_map_type != 0) {
44801 v_src_palette = wuffs_base__make_slice_u8(self->private_data.f_src_palette, 1024);
44802 }
44803 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
44804 wuffs_base__pixel_buffer__pixel_format(a_dst),
44805 wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024)),
44806 wuffs_base__utility__make_pixel_format(self->private_impl.f_src_pixfmt),
44807 v_src_palette,
44808 a_blend);
44809 if ( ! wuffs_base__status__is_ok(&v_status)) {
44810 status = v_status;
44811 if (wuffs_base__status__is_error(&status)) {
44812 goto exit;
44813 } else if (wuffs_base__status__is_suspension(&status)) {
44814 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
44815 goto exit;
44816 }
44817 goto ok;
44818 }
44819 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
44820 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
44821 if ((v_dst_bits_per_pixel & 7) != 0) {
44822 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
44823 goto exit;
44824 }
44825 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
44826 if ((self->private_impl.f_header_image_descriptor & 32) == 0) {
44827 v_dst_y = ((uint32_t)(self->private_impl.f_height - 1));
44828 }
44829 if ((self->private_impl.f_header_image_type & 8) == 0) {
44830 v_lit_length = self->private_impl.f_width;
44831 }
44832 label__resume__continue:;
44833 while (true) {
44834 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
44835 v_dst_palette = wuffs_base__pixel_buffer__palette_or_else(a_dst, wuffs_base__make_slice_u8(self->private_data.f_dst_palette, 1024));
44836 while (v_dst_y < self->private_impl.f_height) {
44837 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y);
44838 v_dst_start = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel);
44839 if (v_dst_start <= ((uint64_t)(v_dst.len))) {
44840 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_start);
44841 } else {
44842 v_dst = wuffs_base__utility__empty_slice_u8();
44843 }
44844 while (v_dst_x < self->private_impl.f_width) {
44845 if (self->private_impl.f_src_bytes_per_pixel > 0) {
44846 if (v_lit_length > 0) {
44847 v_mark = ((uint64_t)(iop_a_src - io0_a_src));
44848 v_num_pixels64 = (((uint64_t)(io2_a_src - iop_a_src)) / ((uint64_t)(self->private_impl.f_src_bytes_per_pixel)));
44849 v_num_pixels32 = ((uint32_t)(wuffs_base__u64__min(v_num_pixels64, ((uint64_t)(v_lit_length)))));
44850 v_num_dst_bytes = (((uint64_t)(v_num_pixels32)) * v_dst_bytes_per_pixel);
44851 v_num_src_bytes = (v_num_pixels32 * self->private_impl.f_src_bytes_per_pixel);
44852 self->private_data.s_decode_frame[0].scratch = v_num_src_bytes;
44853 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
44854 if (self->private_data.s_decode_frame[0].scratch > ((uint64_t)(io2_a_src - iop_a_src))) {
44855 self->private_data.s_decode_frame[0].scratch -= ((uint64_t)(io2_a_src - iop_a_src));
44856 iop_a_src = io2_a_src;
44857 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44858 goto suspend;
44859 }
44860 iop_a_src += self->private_data.s_decode_frame[0].scratch;
44861 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__io__since(v_mark, ((uint64_t)(iop_a_src - io0_a_src)), io0_a_src));
44862 if (v_num_dst_bytes <= ((uint64_t)(v_dst.len))) {
44863 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_num_dst_bytes);
44864 } else {
44865 v_dst = wuffs_base__utility__empty_slice_u8();
44866 }
44867 v_dst_x += v_num_pixels32;
44868 v_lit_length = (((uint32_t)(v_lit_length - v_num_pixels32)) & 65535);
44869 if (v_lit_length > 0) {
44870 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44871 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3);
44872 goto label__resume__continue;
44873 }
44874 } else if (v_run_length > 0) {
44875 v_run_length -= 1;
Nigel Tao123a5c62022-06-03 14:17:20 +100044876 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel));
Nigel Taocc74cb42022-01-19 11:06:15 +110044877 if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) {
44878 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel);
44879 }
44880 v_dst_x += 1;
44881 } else {
44882 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
44883 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44884 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4);
44885 goto label__resume__continue;
44886 }
44887 if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128) {
44888 v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1);
44889 iop_a_src += 1;
44890 if ((v_lit_length + v_dst_x) > self->private_impl.f_width) {
44891 status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding);
44892 goto exit;
44893 }
44894 } else {
44895 if (self->private_impl.f_src_bytes_per_pixel == 1) {
44896 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
44897 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44898 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(5);
44899 goto label__resume__continue;
44900 }
44901 v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127) + 1);
44902 iop_a_src += 1;
44903 self->private_data.f_scratch[0] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44904 iop_a_src += 1;
44905 } else if (self->private_impl.f_src_bytes_per_pixel == 3) {
44906 if (((uint64_t)(io2_a_src - iop_a_src)) < 4) {
44907 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44908 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(6);
44909 goto label__resume__continue;
44910 }
44911 v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127) + 1);
44912 iop_a_src += 1;
44913 self->private_data.f_scratch[0] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44914 iop_a_src += 1;
44915 self->private_data.f_scratch[1] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44916 iop_a_src += 1;
44917 self->private_data.f_scratch[2] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44918 iop_a_src += 1;
44919 } else {
44920 if (((uint64_t)(io2_a_src - iop_a_src)) < 5) {
44921 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44922 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(7);
44923 goto label__resume__continue;
44924 }
44925 v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127) + 1);
44926 iop_a_src += 1;
44927 self->private_data.f_scratch[0] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44928 iop_a_src += 1;
44929 self->private_data.f_scratch[1] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44930 iop_a_src += 1;
44931 self->private_data.f_scratch[2] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44932 iop_a_src += 1;
44933 self->private_data.f_scratch[3] = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
44934 iop_a_src += 1;
44935 }
44936 if ((v_run_length + v_dst_x) > self->private_impl.f_width) {
44937 status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding);
44938 goto exit;
44939 }
44940 }
44941 }
44942 } else {
44943 if (v_lit_length > 0) {
44944 if (((uint64_t)(io2_a_src - iop_a_src)) < 2) {
44945 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44946 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(8);
44947 goto label__resume__continue;
44948 }
44949 v_c = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
44950 iop_a_src += 2;
44951 v_c5 = (31 & (v_c >> 0));
44952 self->private_data.f_scratch[0] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44953 v_c5 = (31 & (v_c >> 5));
44954 self->private_data.f_scratch[1] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44955 v_c5 = (31 & (v_c >> 10));
44956 self->private_data.f_scratch[2] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44957 self->private_data.f_scratch[3] = 255;
44958 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, 4));
44959 if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) {
44960 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel);
44961 }
44962 v_dst_x += 1;
44963 v_lit_length -= 1;
44964 } else if (v_run_length > 0) {
44965 v_run_length -= 1;
Nigel Tao123a5c62022-06-03 14:17:20 +100044966 wuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(&self->private_impl.f_swizzler, v_dst, v_dst_palette, wuffs_base__make_slice_u8(self->private_data.f_scratch, self->private_impl.f_scratch_bytes_per_pixel));
Nigel Taocc74cb42022-01-19 11:06:15 +110044967 if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) {
44968 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel);
44969 }
44970 v_dst_x += 1;
44971 } else {
44972 if (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
44973 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44974 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9);
44975 goto label__resume__continue;
44976 }
44977 if (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) < 128) {
44978 v_lit_length = (((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) + 1);
44979 iop_a_src += 1;
44980 if ((v_lit_length + v_dst_x) > self->private_impl.f_width) {
44981 status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding);
44982 goto exit;
44983 }
44984 } else {
44985 if (((uint64_t)(io2_a_src - iop_a_src)) < 3) {
44986 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
44987 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10);
44988 goto label__resume__continue;
44989 }
44990 v_run_length = ((((uint32_t)(wuffs_base__peek_u8be__no_bounds_check(iop_a_src))) & 127) + 1);
44991 iop_a_src += 1;
44992 v_c = ((uint32_t)(wuffs_base__peek_u16le__no_bounds_check(iop_a_src)));
44993 iop_a_src += 2;
44994 v_c5 = (31 & (v_c >> 0));
44995 self->private_data.f_scratch[0] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44996 v_c5 = (31 & (v_c >> 5));
44997 self->private_data.f_scratch[1] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
44998 v_c5 = (31 & (v_c >> 10));
44999 self->private_data.f_scratch[2] = ((uint8_t)(((v_c5 << 3) | (v_c5 >> 2))));
45000 self->private_data.f_scratch[3] = 255;
45001 if ((v_run_length + v_dst_x) > self->private_impl.f_width) {
45002 status = wuffs_base__make_status(wuffs_tga__error__bad_run_length_encoding);
45003 goto exit;
45004 }
45005 }
45006 }
45007 }
45008 }
45009 v_dst_x = 0;
45010 if ((self->private_impl.f_header_image_descriptor & 32) == 0) {
45011 v_dst_y -= 1;
45012 } else {
45013 v_dst_y += 1;
45014 }
45015 if ((self->private_impl.f_header_image_type & 8) == 0) {
45016 v_lit_length = self->private_impl.f_width;
45017 }
45018 }
45019 goto label__resume__break;
45020 }
45021 label__resume__break:;
Nigel Tao123a5c62022-06-03 14:17:20 +100045022 self->private_impl.f_call_sequence = 96;
Nigel Taocc74cb42022-01-19 11:06:15 +110045023
45024 ok:
45025 self->private_impl.p_decode_frame[0] = 0;
45026 goto exit;
45027 }
45028
45029 goto suspend;
45030 suspend:
45031 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
45032 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
45033 self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel = v_dst_bytes_per_pixel;
45034 self->private_data.s_decode_frame[0].v_dst_x = v_dst_x;
45035 self->private_data.s_decode_frame[0].v_dst_y = v_dst_y;
45036 self->private_data.s_decode_frame[0].v_mark = v_mark;
45037 self->private_data.s_decode_frame[0].v_num_pixels32 = v_num_pixels32;
45038 self->private_data.s_decode_frame[0].v_lit_length = v_lit_length;
45039 self->private_data.s_decode_frame[0].v_run_length = v_run_length;
45040 self->private_data.s_decode_frame[0].v_num_dst_bytes = v_num_dst_bytes;
45041
45042 goto exit;
45043 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110045044 if (a_src && a_src->data.ptr) {
Nigel Taocc74cb42022-01-19 11:06:15 +110045045 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45046 }
45047
45048 if (wuffs_base__status__is_error(&status)) {
45049 self->private_impl.magic = WUFFS_BASE__DISABLED;
45050 }
45051 return status;
45052}
45053
45054// -------- func tga.decoder.frame_dirty_rect
45055
45056WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
45057wuffs_tga__decoder__frame_dirty_rect(
45058 const wuffs_tga__decoder* self) {
45059 if (!self) {
45060 return wuffs_base__utility__empty_rect_ie_u32();
45061 }
45062 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45063 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45064 return wuffs_base__utility__empty_rect_ie_u32();
45065 }
45066
45067 return wuffs_base__utility__make_rect_ie_u32(
45068 0,
45069 0,
45070 self->private_impl.f_width,
45071 self->private_impl.f_height);
45072}
45073
45074// -------- func tga.decoder.num_animation_loops
45075
45076WUFFS_BASE__MAYBE_STATIC uint32_t
45077wuffs_tga__decoder__num_animation_loops(
45078 const wuffs_tga__decoder* self) {
45079 if (!self) {
45080 return 0;
45081 }
45082 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45083 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45084 return 0;
45085 }
45086
45087 return 0;
45088}
45089
45090// -------- func tga.decoder.num_decoded_frame_configs
45091
45092WUFFS_BASE__MAYBE_STATIC uint64_t
45093wuffs_tga__decoder__num_decoded_frame_configs(
45094 const wuffs_tga__decoder* self) {
45095 if (!self) {
45096 return 0;
45097 }
45098 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45099 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45100 return 0;
45101 }
45102
Nigel Tao123a5c62022-06-03 14:17:20 +100045103 if (self->private_impl.f_call_sequence > 32) {
Nigel Taocc74cb42022-01-19 11:06:15 +110045104 return 1;
45105 }
45106 return 0;
45107}
45108
45109// -------- func tga.decoder.num_decoded_frames
45110
45111WUFFS_BASE__MAYBE_STATIC uint64_t
45112wuffs_tga__decoder__num_decoded_frames(
45113 const wuffs_tga__decoder* self) {
45114 if (!self) {
45115 return 0;
45116 }
45117 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45118 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45119 return 0;
45120 }
45121
Nigel Tao123a5c62022-06-03 14:17:20 +100045122 if (self->private_impl.f_call_sequence > 64) {
Nigel Taocc74cb42022-01-19 11:06:15 +110045123 return 1;
45124 }
45125 return 0;
45126}
45127
45128// -------- func tga.decoder.restart_frame
45129
45130WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45131wuffs_tga__decoder__restart_frame(
45132 wuffs_tga__decoder* self,
45133 uint64_t a_index,
45134 uint64_t a_io_position) {
45135 if (!self) {
45136 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45137 }
45138 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45139 return wuffs_base__make_status(
45140 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45141 ? wuffs_base__error__disabled_by_previous_error
45142 : wuffs_base__error__initialize_not_called);
45143 }
45144
Nigel Tao123a5c62022-06-03 14:17:20 +100045145 if (self->private_impl.f_call_sequence < 32) {
Nigel Taocc74cb42022-01-19 11:06:15 +110045146 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
45147 }
45148 if (a_index != 0) {
45149 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45150 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045151 self->private_impl.f_call_sequence = 40;
Nigel Taocc74cb42022-01-19 11:06:15 +110045152 self->private_impl.f_frame_config_io_position = a_io_position;
45153 return wuffs_base__make_status(NULL);
45154}
45155
45156// -------- func tga.decoder.set_report_metadata
45157
45158WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
45159wuffs_tga__decoder__set_report_metadata(
45160 wuffs_tga__decoder* self,
45161 uint32_t a_fourcc,
45162 bool a_report) {
45163 return wuffs_base__make_empty_struct();
45164}
45165
45166// -------- func tga.decoder.tell_me_more
45167
45168WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45169wuffs_tga__decoder__tell_me_more(
45170 wuffs_tga__decoder* self,
45171 wuffs_base__io_buffer* a_dst,
45172 wuffs_base__more_information* a_minfo,
45173 wuffs_base__io_buffer* a_src) {
45174 if (!self) {
45175 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45176 }
45177 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45178 return wuffs_base__make_status(
45179 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45180 ? wuffs_base__error__disabled_by_previous_error
45181 : wuffs_base__error__initialize_not_called);
45182 }
45183 if (!a_dst || !a_src) {
45184 self->private_impl.magic = WUFFS_BASE__DISABLED;
45185 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45186 }
45187 if ((self->private_impl.active_coroutine != 0) &&
45188 (self->private_impl.active_coroutine != 4)) {
45189 self->private_impl.magic = WUFFS_BASE__DISABLED;
45190 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
45191 }
45192 self->private_impl.active_coroutine = 0;
45193 wuffs_base__status status = wuffs_base__make_status(NULL);
45194
45195 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
45196 goto exit;
45197
45198 goto ok;
45199 ok:
45200 goto exit;
45201 exit:
45202 if (wuffs_base__status__is_error(&status)) {
45203 self->private_impl.magic = WUFFS_BASE__DISABLED;
45204 }
45205 return status;
45206}
45207
45208// -------- func tga.decoder.workbuf_len
45209
45210WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
45211wuffs_tga__decoder__workbuf_len(
45212 const wuffs_tga__decoder* self) {
45213 if (!self) {
45214 return wuffs_base__utility__empty_range_ii_u64();
45215 }
45216 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45217 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45218 return wuffs_base__utility__empty_range_ii_u64();
45219 }
45220
45221 return wuffs_base__utility__make_range_ii_u64(0, 0);
45222}
45223
45224#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA)
45225
Nigel Taoe360a532021-04-05 22:47:03 +100045226#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
45227
45228// ---------------- Status Codes Implementations
45229
45230const char wuffs_wbmp__error__bad_header[] = "#wbmp: bad header";
45231
45232// ---------------- Private Consts
45233
45234// ---------------- Private Initializer Prototypes
45235
45236// ---------------- Private Function Prototypes
45237
45238// ---------------- VTables
45239
45240const wuffs_base__image_decoder__func_ptrs
45241wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder = {
45242 (wuffs_base__status(*)(void*,
45243 wuffs_base__pixel_buffer*,
45244 wuffs_base__io_buffer*,
45245 wuffs_base__pixel_blend,
45246 wuffs_base__slice_u8,
45247 wuffs_base__decode_frame_options*))(&wuffs_wbmp__decoder__decode_frame),
45248 (wuffs_base__status(*)(void*,
45249 wuffs_base__frame_config*,
45250 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_frame_config),
45251 (wuffs_base__status(*)(void*,
45252 wuffs_base__image_config*,
45253 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__decode_image_config),
45254 (wuffs_base__rect_ie_u32(*)(const void*))(&wuffs_wbmp__decoder__frame_dirty_rect),
45255 (uint32_t(*)(const void*))(&wuffs_wbmp__decoder__num_animation_loops),
45256 (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frame_configs),
45257 (uint64_t(*)(const void*))(&wuffs_wbmp__decoder__num_decoded_frames),
45258 (wuffs_base__status(*)(void*,
45259 uint64_t,
45260 uint64_t))(&wuffs_wbmp__decoder__restart_frame),
45261 (wuffs_base__empty_struct(*)(void*,
45262 uint32_t,
45263 bool))(&wuffs_wbmp__decoder__set_quirk_enabled),
45264 (wuffs_base__empty_struct(*)(void*,
45265 uint32_t,
45266 bool))(&wuffs_wbmp__decoder__set_report_metadata),
45267 (wuffs_base__status(*)(void*,
45268 wuffs_base__io_buffer*,
45269 wuffs_base__more_information*,
45270 wuffs_base__io_buffer*))(&wuffs_wbmp__decoder__tell_me_more),
45271 (wuffs_base__range_ii_u64(*)(const void*))(&wuffs_wbmp__decoder__workbuf_len),
45272};
45273
45274// ---------------- Initializer Implementations
45275
45276wuffs_base__status WUFFS_BASE__WARN_UNUSED_RESULT
45277wuffs_wbmp__decoder__initialize(
45278 wuffs_wbmp__decoder* self,
45279 size_t sizeof_star_self,
45280 uint64_t wuffs_version,
45281 uint32_t options){
45282 if (!self) {
45283 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45284 }
45285 if (sizeof(*self) != sizeof_star_self) {
45286 return wuffs_base__make_status(wuffs_base__error__bad_sizeof_receiver);
45287 }
45288 if (((wuffs_version >> 32) != WUFFS_VERSION_MAJOR) ||
45289 (((wuffs_version >> 16) & 0xFFFF) > WUFFS_VERSION_MINOR)) {
45290 return wuffs_base__make_status(wuffs_base__error__bad_wuffs_version);
45291 }
45292
45293 if ((options & WUFFS_INITIALIZE__ALREADY_ZEROED) != 0) {
45294 // The whole point of this if-check is to detect an uninitialized *self.
45295 // We disable the warning on GCC. Clang-5.0 does not have this warning.
45296#if !defined(__clang__) && defined(__GNUC__)
45297#pragma GCC diagnostic push
45298#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
45299#endif
45300 if (self->private_impl.magic != 0) {
45301 return wuffs_base__make_status(wuffs_base__error__initialize_falsely_claimed_already_zeroed);
45302 }
45303#if !defined(__clang__) && defined(__GNUC__)
45304#pragma GCC diagnostic pop
45305#endif
45306 } else {
45307 if ((options & WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED) == 0) {
45308 memset(self, 0, sizeof(*self));
45309 options |= WUFFS_INITIALIZE__ALREADY_ZEROED;
45310 } else {
45311 memset(&(self->private_impl), 0, sizeof(self->private_impl));
45312 }
45313 }
45314
45315 self->private_impl.magic = WUFFS_BASE__MAGIC;
45316 self->private_impl.vtable_for__wuffs_base__image_decoder.vtable_name =
45317 wuffs_base__image_decoder__vtable_name;
45318 self->private_impl.vtable_for__wuffs_base__image_decoder.function_pointers =
45319 (const void*)(&wuffs_wbmp__decoder__func_ptrs_for__wuffs_base__image_decoder);
45320 return wuffs_base__make_status(NULL);
45321}
45322
45323wuffs_wbmp__decoder*
45324wuffs_wbmp__decoder__alloc() {
45325 wuffs_wbmp__decoder* x =
45326 (wuffs_wbmp__decoder*)(calloc(sizeof(wuffs_wbmp__decoder), 1));
45327 if (!x) {
45328 return NULL;
45329 }
45330 if (wuffs_wbmp__decoder__initialize(
45331 x, sizeof(wuffs_wbmp__decoder), WUFFS_VERSION, WUFFS_INITIALIZE__ALREADY_ZEROED).repr) {
45332 free(x);
45333 return NULL;
45334 }
45335 return x;
45336}
45337
45338size_t
45339sizeof__wuffs_wbmp__decoder() {
45340 return sizeof(wuffs_wbmp__decoder);
45341}
45342
45343// ---------------- Function Implementations
45344
45345// -------- func wbmp.decoder.set_quirk_enabled
45346
45347WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
45348wuffs_wbmp__decoder__set_quirk_enabled(
45349 wuffs_wbmp__decoder* self,
45350 uint32_t a_quirk,
45351 bool a_enabled) {
45352 return wuffs_base__make_empty_struct();
45353}
45354
45355// -------- func wbmp.decoder.decode_image_config
45356
45357WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45358wuffs_wbmp__decoder__decode_image_config(
45359 wuffs_wbmp__decoder* self,
45360 wuffs_base__image_config* a_dst,
45361 wuffs_base__io_buffer* a_src) {
45362 if (!self) {
45363 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45364 }
45365 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45366 return wuffs_base__make_status(
45367 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45368 ? wuffs_base__error__disabled_by_previous_error
45369 : wuffs_base__error__initialize_not_called);
45370 }
45371 if (!a_src) {
45372 self->private_impl.magic = WUFFS_BASE__DISABLED;
45373 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45374 }
45375 if ((self->private_impl.active_coroutine != 0) &&
45376 (self->private_impl.active_coroutine != 1)) {
45377 self->private_impl.magic = WUFFS_BASE__DISABLED;
45378 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
45379 }
45380 self->private_impl.active_coroutine = 0;
45381 wuffs_base__status status = wuffs_base__make_status(NULL);
45382
45383 uint8_t v_c = 0;
45384 uint32_t v_i = 0;
45385 uint32_t v_x32 = 0;
45386 uint64_t v_x64 = 0;
45387
45388 const uint8_t* iop_a_src = NULL;
45389 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45390 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45391 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110045392 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045393 io0_a_src = a_src->data.ptr;
45394 io1_a_src = io0_a_src + a_src->meta.ri;
45395 iop_a_src = io1_a_src;
45396 io2_a_src = io0_a_src + a_src->meta.wi;
45397 }
45398
45399 uint32_t coro_susp_point = self->private_impl.p_decode_image_config[0];
45400 if (coro_susp_point) {
45401 v_i = self->private_data.s_decode_image_config[0].v_i;
45402 v_x32 = self->private_data.s_decode_image_config[0].v_x32;
45403 }
45404 switch (coro_susp_point) {
45405 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
45406
45407 if (self->private_impl.f_call_sequence != 0) {
45408 status = wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
45409 goto exit;
45410 }
45411 v_i = 0;
45412 while (v_i < 2) {
45413 {
45414 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
45415 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
45416 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
45417 goto suspend;
45418 }
45419 uint8_t t_0 = *iop_a_src++;
45420 v_c = t_0;
45421 }
45422 if (v_c != 0) {
45423 status = wuffs_base__make_status(wuffs_wbmp__error__bad_header);
45424 goto exit;
45425 }
45426 v_i += 1;
45427 }
45428 v_i = 0;
45429 while (v_i < 2) {
45430 v_x32 = 0;
45431 while (true) {
45432 {
45433 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(2);
45434 if (WUFFS_BASE__UNLIKELY(iop_a_src == io2_a_src)) {
45435 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
45436 goto suspend;
45437 }
45438 uint8_t t_1 = *iop_a_src++;
45439 v_c = t_1;
45440 }
45441 v_x32 |= ((uint32_t)((v_c & 127)));
45442 if ((v_c >> 7) == 0) {
45443 goto label__0__break;
45444 }
45445 v_x64 = (((uint64_t)(v_x32)) << 7);
45446 if (v_x64 > 4294967295) {
45447 status = wuffs_base__make_status(wuffs_wbmp__error__bad_header);
45448 goto exit;
45449 }
45450 v_x32 = ((uint32_t)(v_x64));
45451 }
45452 label__0__break:;
45453 if (v_i == 0) {
45454 self->private_impl.f_width = v_x32;
45455 } else {
45456 self->private_impl.f_height = v_x32;
45457 }
45458 v_i += 1;
45459 }
Nigel Taoc9d2ed72021-08-15 13:50:22 +100045460 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 +100045461 if (a_dst != NULL) {
45462 wuffs_base__image_config__set(
45463 a_dst,
45464 2198077448,
45465 0,
45466 self->private_impl.f_width,
45467 self->private_impl.f_height,
45468 self->private_impl.f_frame_config_io_position,
45469 true);
45470 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045471 self->private_impl.f_call_sequence = 32;
Nigel Taoe360a532021-04-05 22:47:03 +100045472
45473 goto ok;
45474 ok:
45475 self->private_impl.p_decode_image_config[0] = 0;
45476 goto exit;
45477 }
45478
45479 goto suspend;
45480 suspend:
45481 self->private_impl.p_decode_image_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
45482 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 1 : 0;
45483 self->private_data.s_decode_image_config[0].v_i = v_i;
45484 self->private_data.s_decode_image_config[0].v_x32 = v_x32;
45485
45486 goto exit;
45487 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110045488 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045489 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45490 }
45491
45492 if (wuffs_base__status__is_error(&status)) {
45493 self->private_impl.magic = WUFFS_BASE__DISABLED;
45494 }
45495 return status;
45496}
45497
45498// -------- func wbmp.decoder.decode_frame_config
45499
45500WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45501wuffs_wbmp__decoder__decode_frame_config(
45502 wuffs_wbmp__decoder* self,
45503 wuffs_base__frame_config* a_dst,
45504 wuffs_base__io_buffer* a_src) {
45505 if (!self) {
45506 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45507 }
45508 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45509 return wuffs_base__make_status(
45510 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45511 ? wuffs_base__error__disabled_by_previous_error
45512 : wuffs_base__error__initialize_not_called);
45513 }
45514 if (!a_src) {
45515 self->private_impl.magic = WUFFS_BASE__DISABLED;
45516 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45517 }
45518 if ((self->private_impl.active_coroutine != 0) &&
45519 (self->private_impl.active_coroutine != 2)) {
45520 self->private_impl.magic = WUFFS_BASE__DISABLED;
45521 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
45522 }
45523 self->private_impl.active_coroutine = 0;
45524 wuffs_base__status status = wuffs_base__make_status(NULL);
45525
45526 const uint8_t* iop_a_src = NULL;
45527 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45528 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45529 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110045530 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045531 io0_a_src = a_src->data.ptr;
45532 io1_a_src = io0_a_src + a_src->meta.ri;
45533 iop_a_src = io1_a_src;
45534 io2_a_src = io0_a_src + a_src->meta.wi;
45535 }
45536
45537 uint32_t coro_susp_point = self->private_impl.p_decode_frame_config[0];
45538 switch (coro_susp_point) {
45539 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
45540
Nigel Tao123a5c62022-06-03 14:17:20 +100045541 if (self->private_impl.f_call_sequence == 32) {
45542 } else if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100045543 if (a_src) {
45544 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45545 }
45546 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
45547 status = wuffs_wbmp__decoder__decode_image_config(self, NULL, a_src);
45548 if (a_src) {
45549 iop_a_src = a_src->data.ptr + a_src->meta.ri;
45550 }
45551 if (status.repr) {
45552 goto suspend;
45553 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045554 } else if (self->private_impl.f_call_sequence == 40) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100045555 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 +100045556 status = wuffs_base__make_status(wuffs_base__error__bad_restart);
45557 goto exit;
45558 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045559 } else if (self->private_impl.f_call_sequence == 64) {
45560 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100045561 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
45562 goto ok;
45563 } else {
45564 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
45565 goto ok;
45566 }
45567 if (a_dst != NULL) {
45568 wuffs_base__frame_config__set(
45569 a_dst,
45570 wuffs_base__utility__make_rect_ie_u32(
45571 0,
45572 0,
45573 self->private_impl.f_width,
45574 self->private_impl.f_height),
45575 ((wuffs_base__flicks)(0)),
45576 0,
45577 self->private_impl.f_frame_config_io_position,
45578 0,
45579 true,
45580 false,
45581 4278190080);
45582 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045583 self->private_impl.f_call_sequence = 64;
Nigel Taoe360a532021-04-05 22:47:03 +100045584
Nigel Taoe360a532021-04-05 22:47:03 +100045585 ok:
45586 self->private_impl.p_decode_frame_config[0] = 0;
45587 goto exit;
45588 }
45589
45590 goto suspend;
45591 suspend:
45592 self->private_impl.p_decode_frame_config[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
45593 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 2 : 0;
45594
45595 goto exit;
45596 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110045597 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045598 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45599 }
45600
45601 if (wuffs_base__status__is_error(&status)) {
45602 self->private_impl.magic = WUFFS_BASE__DISABLED;
45603 }
45604 return status;
45605}
45606
45607// -------- func wbmp.decoder.decode_frame
45608
45609WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45610wuffs_wbmp__decoder__decode_frame(
45611 wuffs_wbmp__decoder* self,
45612 wuffs_base__pixel_buffer* a_dst,
45613 wuffs_base__io_buffer* a_src,
45614 wuffs_base__pixel_blend a_blend,
45615 wuffs_base__slice_u8 a_workbuf,
45616 wuffs_base__decode_frame_options* a_opts) {
45617 if (!self) {
45618 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45619 }
45620 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45621 return wuffs_base__make_status(
45622 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45623 ? wuffs_base__error__disabled_by_previous_error
45624 : wuffs_base__error__initialize_not_called);
45625 }
45626 if (!a_dst || !a_src) {
45627 self->private_impl.magic = WUFFS_BASE__DISABLED;
45628 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45629 }
45630 if ((self->private_impl.active_coroutine != 0) &&
45631 (self->private_impl.active_coroutine != 3)) {
45632 self->private_impl.magic = WUFFS_BASE__DISABLED;
45633 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
45634 }
45635 self->private_impl.active_coroutine = 0;
45636 wuffs_base__status status = wuffs_base__make_status(NULL);
45637
45638 wuffs_base__status v_status = wuffs_base__make_status(NULL);
45639 wuffs_base__pixel_format v_dst_pixfmt = {0};
45640 uint32_t v_dst_bits_per_pixel = 0;
45641 uint64_t v_dst_bytes_per_pixel = 0;
45642 uint64_t v_dst_x_in_bytes = 0;
45643 uint32_t v_dst_x = 0;
45644 uint32_t v_dst_y = 0;
45645 wuffs_base__table_u8 v_tab = {0};
45646 wuffs_base__slice_u8 v_dst = {0};
45647 uint8_t v_src[1] = {0};
45648 uint8_t v_c = 0;
45649
45650 const uint8_t* iop_a_src = NULL;
45651 const uint8_t* io0_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45652 const uint8_t* io1_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
45653 const uint8_t* io2_a_src WUFFS_BASE__POTENTIALLY_UNUSED = NULL;
Nigel Taoa0041ac2022-10-20 11:24:24 +110045654 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045655 io0_a_src = a_src->data.ptr;
45656 io1_a_src = io0_a_src + a_src->meta.ri;
45657 iop_a_src = io1_a_src;
45658 io2_a_src = io0_a_src + a_src->meta.wi;
45659 }
45660
45661 uint32_t coro_susp_point = self->private_impl.p_decode_frame[0];
45662 if (coro_susp_point) {
45663 v_dst_bytes_per_pixel = self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel;
45664 v_dst_x = self->private_data.s_decode_frame[0].v_dst_x;
45665 v_dst_y = self->private_data.s_decode_frame[0].v_dst_y;
45666 memcpy(v_src, self->private_data.s_decode_frame[0].v_src, sizeof(v_src));
45667 v_c = self->private_data.s_decode_frame[0].v_c;
45668 }
45669 switch (coro_susp_point) {
45670 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_0;
45671
Nigel Tao123a5c62022-06-03 14:17:20 +100045672 if (self->private_impl.f_call_sequence == 64) {
45673 } else if (self->private_impl.f_call_sequence < 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100045674 if (a_src) {
45675 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45676 }
45677 WUFFS_BASE__COROUTINE_SUSPENSION_POINT(1);
45678 status = wuffs_wbmp__decoder__decode_frame_config(self, NULL, a_src);
45679 if (a_src) {
45680 iop_a_src = a_src->data.ptr + a_src->meta.ri;
45681 }
45682 if (status.repr) {
45683 goto suspend;
45684 }
Nigel Taoe360a532021-04-05 22:47:03 +100045685 } else {
45686 status = wuffs_base__make_status(wuffs_base__note__end_of_data);
45687 goto ok;
45688 }
45689 v_status = wuffs_base__pixel_swizzler__prepare(&self->private_impl.f_swizzler,
45690 wuffs_base__pixel_buffer__pixel_format(a_dst),
45691 wuffs_base__pixel_buffer__palette(a_dst),
45692 wuffs_base__utility__make_pixel_format(536870920),
45693 wuffs_base__utility__empty_slice_u8(),
45694 a_blend);
45695 if ( ! wuffs_base__status__is_ok(&v_status)) {
45696 status = v_status;
45697 if (wuffs_base__status__is_error(&status)) {
45698 goto exit;
45699 } else if (wuffs_base__status__is_suspension(&status)) {
45700 status = wuffs_base__make_status(wuffs_base__error__cannot_return_a_suspension);
45701 goto exit;
45702 }
45703 goto ok;
45704 }
45705 v_dst_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_dst);
45706 v_dst_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_dst_pixfmt);
45707 if ((v_dst_bits_per_pixel & 7) != 0) {
45708 status = wuffs_base__make_status(wuffs_base__error__unsupported_option);
45709 goto exit;
45710 }
45711 v_dst_bytes_per_pixel = ((uint64_t)((v_dst_bits_per_pixel / 8)));
45712 if (self->private_impl.f_width > 0) {
45713 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
45714 while (v_dst_y < self->private_impl.f_height) {
Nigel Taobf9dab32021-11-18 19:19:55 +110045715 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100045716 v_dst_x = 0;
45717 while (v_dst_x < self->private_impl.f_width) {
45718 if ((v_dst_x & 7) == 0) {
45719 while (((uint64_t)(io2_a_src - iop_a_src)) <= 0) {
45720 status = wuffs_base__make_status(wuffs_base__suspension__short_read);
45721 WUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2);
45722 v_tab = wuffs_base__pixel_buffer__plane(a_dst, 0);
Nigel Taobf9dab32021-11-18 19:19:55 +110045723 v_dst = wuffs_base__table_u8__row_u32(v_tab, v_dst_y);
Nigel Taoe360a532021-04-05 22:47:03 +100045724 v_dst_x_in_bytes = (((uint64_t)(v_dst_x)) * v_dst_bytes_per_pixel);
45725 if (v_dst_x_in_bytes <= ((uint64_t)(v_dst.len))) {
45726 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_x_in_bytes);
45727 }
45728 }
45729 v_c = wuffs_base__peek_u8be__no_bounds_check(iop_a_src);
45730 iop_a_src += 1;
45731 }
45732 if ((v_c & 128) == 0) {
45733 v_src[0] = 0;
45734 } else {
45735 v_src[0] = 255;
45736 }
45737 v_c = ((uint8_t)(((((uint32_t)(v_c)) << 1) & 255)));
45738 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));
45739 if (v_dst_bytes_per_pixel <= ((uint64_t)(v_dst.len))) {
45740 v_dst = wuffs_base__slice_u8__subslice_i(v_dst, v_dst_bytes_per_pixel);
45741 }
45742 v_dst_x += 1;
45743 }
45744 v_dst_y += 1;
45745 }
45746 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045747 self->private_impl.f_call_sequence = 96;
Nigel Taoe360a532021-04-05 22:47:03 +100045748
Nigel Taoe360a532021-04-05 22:47:03 +100045749 ok:
45750 self->private_impl.p_decode_frame[0] = 0;
45751 goto exit;
45752 }
45753
45754 goto suspend;
45755 suspend:
45756 self->private_impl.p_decode_frame[0] = wuffs_base__status__is_suspension(&status) ? coro_susp_point : 0;
45757 self->private_impl.active_coroutine = wuffs_base__status__is_suspension(&status) ? 3 : 0;
45758 self->private_data.s_decode_frame[0].v_dst_bytes_per_pixel = v_dst_bytes_per_pixel;
45759 self->private_data.s_decode_frame[0].v_dst_x = v_dst_x;
45760 self->private_data.s_decode_frame[0].v_dst_y = v_dst_y;
45761 memcpy(self->private_data.s_decode_frame[0].v_src, v_src, sizeof(v_src));
45762 self->private_data.s_decode_frame[0].v_c = v_c;
45763
45764 goto exit;
45765 exit:
Nigel Taoa0041ac2022-10-20 11:24:24 +110045766 if (a_src && a_src->data.ptr) {
Nigel Taoe360a532021-04-05 22:47:03 +100045767 a_src->meta.ri = ((size_t)(iop_a_src - a_src->data.ptr));
45768 }
45769
45770 if (wuffs_base__status__is_error(&status)) {
45771 self->private_impl.magic = WUFFS_BASE__DISABLED;
45772 }
45773 return status;
45774}
45775
45776// -------- func wbmp.decoder.frame_dirty_rect
45777
45778WUFFS_BASE__MAYBE_STATIC wuffs_base__rect_ie_u32
45779wuffs_wbmp__decoder__frame_dirty_rect(
45780 const wuffs_wbmp__decoder* self) {
45781 if (!self) {
45782 return wuffs_base__utility__empty_rect_ie_u32();
45783 }
45784 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45785 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45786 return wuffs_base__utility__empty_rect_ie_u32();
45787 }
45788
45789 return wuffs_base__utility__make_rect_ie_u32(
45790 0,
45791 0,
45792 self->private_impl.f_width,
45793 self->private_impl.f_height);
45794}
45795
45796// -------- func wbmp.decoder.num_animation_loops
45797
45798WUFFS_BASE__MAYBE_STATIC uint32_t
45799wuffs_wbmp__decoder__num_animation_loops(
45800 const wuffs_wbmp__decoder* self) {
45801 if (!self) {
45802 return 0;
45803 }
45804 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45805 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45806 return 0;
45807 }
45808
45809 return 0;
45810}
45811
45812// -------- func wbmp.decoder.num_decoded_frame_configs
45813
45814WUFFS_BASE__MAYBE_STATIC uint64_t
45815wuffs_wbmp__decoder__num_decoded_frame_configs(
45816 const wuffs_wbmp__decoder* self) {
45817 if (!self) {
45818 return 0;
45819 }
45820 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45821 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45822 return 0;
45823 }
45824
Nigel Tao123a5c62022-06-03 14:17:20 +100045825 if (self->private_impl.f_call_sequence > 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100045826 return 1;
45827 }
45828 return 0;
45829}
45830
45831// -------- func wbmp.decoder.num_decoded_frames
45832
45833WUFFS_BASE__MAYBE_STATIC uint64_t
45834wuffs_wbmp__decoder__num_decoded_frames(
45835 const wuffs_wbmp__decoder* self) {
45836 if (!self) {
45837 return 0;
45838 }
45839 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45840 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45841 return 0;
45842 }
45843
Nigel Tao123a5c62022-06-03 14:17:20 +100045844 if (self->private_impl.f_call_sequence > 64) {
Nigel Taoe360a532021-04-05 22:47:03 +100045845 return 1;
45846 }
45847 return 0;
45848}
45849
45850// -------- func wbmp.decoder.restart_frame
45851
45852WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45853wuffs_wbmp__decoder__restart_frame(
45854 wuffs_wbmp__decoder* self,
45855 uint64_t a_index,
45856 uint64_t a_io_position) {
45857 if (!self) {
45858 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45859 }
45860 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45861 return wuffs_base__make_status(
45862 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45863 ? wuffs_base__error__disabled_by_previous_error
45864 : wuffs_base__error__initialize_not_called);
45865 }
45866
Nigel Tao123a5c62022-06-03 14:17:20 +100045867 if (self->private_impl.f_call_sequence < 32) {
Nigel Taoe360a532021-04-05 22:47:03 +100045868 return wuffs_base__make_status(wuffs_base__error__bad_call_sequence);
45869 }
45870 if (a_index != 0) {
45871 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45872 }
Nigel Tao123a5c62022-06-03 14:17:20 +100045873 self->private_impl.f_call_sequence = 40;
Nigel Taoe360a532021-04-05 22:47:03 +100045874 self->private_impl.f_frame_config_io_position = a_io_position;
45875 return wuffs_base__make_status(NULL);
45876}
45877
45878// -------- func wbmp.decoder.set_report_metadata
45879
45880WUFFS_BASE__MAYBE_STATIC wuffs_base__empty_struct
45881wuffs_wbmp__decoder__set_report_metadata(
45882 wuffs_wbmp__decoder* self,
45883 uint32_t a_fourcc,
45884 bool a_report) {
45885 return wuffs_base__make_empty_struct();
45886}
45887
45888// -------- func wbmp.decoder.tell_me_more
45889
45890WUFFS_BASE__MAYBE_STATIC wuffs_base__status
45891wuffs_wbmp__decoder__tell_me_more(
45892 wuffs_wbmp__decoder* self,
45893 wuffs_base__io_buffer* a_dst,
45894 wuffs_base__more_information* a_minfo,
45895 wuffs_base__io_buffer* a_src) {
45896 if (!self) {
45897 return wuffs_base__make_status(wuffs_base__error__bad_receiver);
45898 }
45899 if (self->private_impl.magic != WUFFS_BASE__MAGIC) {
45900 return wuffs_base__make_status(
45901 (self->private_impl.magic == WUFFS_BASE__DISABLED)
45902 ? wuffs_base__error__disabled_by_previous_error
45903 : wuffs_base__error__initialize_not_called);
45904 }
45905 if (!a_dst || !a_src) {
45906 self->private_impl.magic = WUFFS_BASE__DISABLED;
45907 return wuffs_base__make_status(wuffs_base__error__bad_argument);
45908 }
45909 if ((self->private_impl.active_coroutine != 0) &&
45910 (self->private_impl.active_coroutine != 4)) {
45911 self->private_impl.magic = WUFFS_BASE__DISABLED;
45912 return wuffs_base__make_status(wuffs_base__error__interleaved_coroutine_calls);
45913 }
45914 self->private_impl.active_coroutine = 0;
45915 wuffs_base__status status = wuffs_base__make_status(NULL);
45916
45917 status = wuffs_base__make_status(wuffs_base__error__no_more_information);
45918 goto exit;
45919
45920 goto ok;
45921 ok:
45922 goto exit;
45923 exit:
45924 if (wuffs_base__status__is_error(&status)) {
45925 self->private_impl.magic = WUFFS_BASE__DISABLED;
45926 }
45927 return status;
45928}
45929
45930// -------- func wbmp.decoder.workbuf_len
45931
45932WUFFS_BASE__MAYBE_STATIC wuffs_base__range_ii_u64
45933wuffs_wbmp__decoder__workbuf_len(
45934 const wuffs_wbmp__decoder* self) {
45935 if (!self) {
45936 return wuffs_base__utility__empty_range_ii_u64();
45937 }
45938 if ((self->private_impl.magic != WUFFS_BASE__MAGIC) &&
45939 (self->private_impl.magic != WUFFS_BASE__DISABLED)) {
45940 return wuffs_base__utility__empty_range_ii_u64();
45941 }
45942
45943 return wuffs_base__utility__make_range_ii_u64(0, 0);
45944}
45945
45946#endif // !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
45947
45948#if defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
45949
45950// ---------------- Auxiliary - Base
45951
45952// Auxiliary code is discussed at
45953// https://github.com/google/wuffs/blob/main/doc/note/auxiliary-code.md
45954
45955#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__BASE)
45956
45957namespace wuffs_aux {
45958
45959namespace sync_io {
45960
45961// --------
45962
Nigel Taobf9dab32021-11-18 19:19:55 +110045963DynIOBuffer::DynIOBuffer(uint64_t max_incl)
45964 : m_buf(wuffs_base__empty_io_buffer()), m_max_incl(max_incl) {}
45965
45966DynIOBuffer::~DynIOBuffer() {
45967 if (m_buf.data.ptr) {
45968 free(m_buf.data.ptr);
45969 }
45970}
45971
45972void //
45973DynIOBuffer::drop() {
45974 if (m_buf.data.ptr) {
45975 free(m_buf.data.ptr);
45976 }
45977 m_buf = wuffs_base__empty_io_buffer();
45978}
45979
45980DynIOBuffer::GrowResult //
45981DynIOBuffer::grow(uint64_t min_incl) {
45982 uint64_t n = round_up(min_incl, m_max_incl);
45983 if (n == 0) {
45984 return ((min_incl == 0) && (m_max_incl == 0))
45985 ? DynIOBuffer::GrowResult::OK
45986 : DynIOBuffer::GrowResult::FailedMaxInclExceeded;
45987 } else if (n > m_buf.data.len) {
45988 uint8_t* ptr = static_cast<uint8_t*>(realloc(m_buf.data.ptr, n));
45989 if (!ptr) {
45990 return DynIOBuffer::GrowResult::FailedOutOfMemory;
45991 }
45992 m_buf.data.ptr = ptr;
45993 m_buf.data.len = n;
45994 }
45995 return DynIOBuffer::GrowResult::OK;
45996}
45997
45998// round_up rounds min_incl up, returning the smallest value x satisfying
45999// (min_incl <= x) and (x <= max_incl) and some other constraints. It returns 0
46000// if there is no such x.
46001//
46002// When max_incl <= 4096, the other constraints are:
46003// - (x == max_incl)
46004//
46005// When max_incl > 4096, the other constraints are:
46006// - (x == max_incl) or (x is a power of 2)
46007// - (x >= 4096)
46008uint64_t //
46009DynIOBuffer::round_up(uint64_t min_incl, uint64_t max_incl) {
46010 if (min_incl > max_incl) {
46011 return 0;
46012 }
46013 uint64_t n = 4096;
46014 if (n >= max_incl) {
46015 return max_incl;
46016 }
46017 while (n < min_incl) {
46018 if (n >= (max_incl / 2)) {
46019 return max_incl;
46020 }
46021 n *= 2;
46022 }
46023 return n;
46024}
46025
46026// --------
46027
Nigel Taoe360a532021-04-05 22:47:03 +100046028Input::~Input() {}
46029
46030IOBuffer* //
46031Input::BringsItsOwnIOBuffer() {
46032 return nullptr;
46033}
46034
46035// --------
46036
46037FileInput::FileInput(FILE* f) : m_f(f) {}
46038
46039std::string //
46040FileInput::CopyIn(IOBuffer* dst) {
46041 if (!m_f) {
46042 return "wuffs_aux::sync_io::FileInput: nullptr file";
46043 } else if (!dst) {
46044 return "wuffs_aux::sync_io::FileInput: nullptr IOBuffer";
46045 } else if (dst->meta.closed) {
46046 return "wuffs_aux::sync_io::FileInput: end of file";
46047 } else {
46048 dst->compact();
46049 size_t n = fread(dst->writer_pointer(), 1, dst->writer_length(), m_f);
46050 dst->meta.wi += n;
46051 dst->meta.closed = feof(m_f);
46052 if (ferror(m_f)) {
46053 return "wuffs_aux::sync_io::FileInput: error reading file";
46054 }
46055 }
46056 return "";
46057}
46058
46059// --------
46060
46061MemoryInput::MemoryInput(const char* ptr, size_t len)
46062 : m_io(wuffs_base__ptr_u8__reader(
46063 static_cast<uint8_t*>(static_cast<void*>(const_cast<char*>(ptr))),
46064 len,
46065 true)) {}
46066
46067MemoryInput::MemoryInput(const uint8_t* ptr, size_t len)
46068 : m_io(wuffs_base__ptr_u8__reader(const_cast<uint8_t*>(ptr), len, true)) {}
46069
46070IOBuffer* //
46071MemoryInput::BringsItsOwnIOBuffer() {
46072 return &m_io;
46073}
46074
46075std::string //
46076MemoryInput::CopyIn(IOBuffer* dst) {
46077 if (!dst) {
46078 return "wuffs_aux::sync_io::MemoryInput: nullptr IOBuffer";
46079 } else if (dst->meta.closed) {
46080 return "wuffs_aux::sync_io::MemoryInput: end of file";
46081 } else if (wuffs_base__slice_u8__overlaps(dst->data, m_io.data)) {
46082 // Treat m_io's data as immutable, so don't compact dst or otherwise write
46083 // to it.
46084 return "wuffs_aux::sync_io::MemoryInput: overlapping buffers";
46085 } else {
46086 dst->compact();
46087 size_t nd = dst->writer_length();
46088 size_t ns = m_io.reader_length();
46089 size_t n = (nd < ns) ? nd : ns;
46090 memcpy(dst->writer_pointer(), m_io.reader_pointer(), n);
46091 m_io.meta.ri += n;
46092 dst->meta.wi += n;
46093 dst->meta.closed = m_io.reader_length() == 0;
46094 }
46095 return "";
46096}
46097
46098// --------
46099
46100} // namespace sync_io
46101
Nigel Taobf9dab32021-11-18 19:19:55 +110046102namespace private_impl {
46103
46104struct ErrorMessages {
46105 const char* max_incl_metadata_length_exceeded;
46106 const char* out_of_memory;
46107 const char* unexpected_end_of_file;
46108 const char* unsupported_metadata;
46109 const char* unsupported_negative_advance;
46110
46111 // If adding new "const char*" typed fields to this struct, either add them
46112 // after existing fields or, if re-ordering fields, make sure that you update
46113 // all of the "const private_impl::ErrorMessages FooBarErrorMessages" values
46114 // in all of the sibling *.cc files.
46115
46116 static inline const char* resolve(const char* s) {
46117 return s ? s : "wuffs_aux::private_impl: unknown error";
46118 };
46119};
46120
46121std::string //
46122AdvanceIOBufferTo(const ErrorMessages& error_messages,
46123 sync_io::Input& input,
46124 IOBuffer& io_buf,
46125 uint64_t absolute_position) {
46126 if (absolute_position < io_buf.reader_position()) {
46127 return error_messages.resolve(error_messages.unsupported_negative_advance);
46128 }
46129 while (true) {
46130 uint64_t relative_position = absolute_position - io_buf.reader_position();
46131 if (relative_position <= io_buf.reader_length()) {
46132 io_buf.meta.ri += (size_t)relative_position;
46133 break;
46134 } else if (io_buf.meta.closed) {
46135 return error_messages.resolve(error_messages.unexpected_end_of_file);
46136 }
46137 io_buf.meta.ri = io_buf.meta.wi;
46138 if (!input.BringsItsOwnIOBuffer()) {
46139 io_buf.compact();
46140 }
46141 std::string error_message = input.CopyIn(&io_buf);
46142 if (!error_message.empty()) {
46143 return error_message;
46144 }
46145 }
46146 return "";
46147}
46148
46149std::string //
46150HandleMetadata(
46151 const ErrorMessages& error_messages,
46152 sync_io::Input& input,
46153 wuffs_base__io_buffer& io_buf,
46154 sync_io::DynIOBuffer& raw,
46155 wuffs_base__status (*tell_me_more_func)(void*,
46156 wuffs_base__io_buffer*,
46157 wuffs_base__more_information*,
46158 wuffs_base__io_buffer*),
46159 void* tell_me_more_receiver,
46160 std::string (*handle_metadata_func)(void*,
46161 const wuffs_base__more_information*,
46162 wuffs_base__slice_u8),
46163 void* handle_metadata_receiver) {
46164 wuffs_base__more_information minfo = wuffs_base__empty_more_information();
46165 // Reset raw but keep its backing array (the raw.m_buf.data slice).
46166 raw.m_buf.meta = wuffs_base__empty_io_buffer_meta();
46167
46168 while (true) {
46169 minfo = wuffs_base__empty_more_information();
46170 wuffs_base__status status = (*tell_me_more_func)(
46171 tell_me_more_receiver, &raw.m_buf, &minfo, &io_buf);
46172 switch (minfo.flavor) {
46173 case 0:
46174 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_TRANSFORM:
46175 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_PARSED:
46176 break;
46177
46178 case WUFFS_BASE__MORE_INFORMATION__FLAVOR__METADATA_RAW_PASSTHROUGH: {
46179 wuffs_base__range_ie_u64 r = minfo.metadata_raw_passthrough__range();
46180 if (r.is_empty()) {
46181 break;
46182 }
46183 uint64_t num_to_copy = r.length();
46184 if (num_to_copy > (raw.m_max_incl - raw.m_buf.meta.wi)) {
46185 return error_messages.resolve(
46186 error_messages.max_incl_metadata_length_exceeded);
46187 } else if (num_to_copy > (raw.m_buf.data.len - raw.m_buf.meta.wi)) {
46188 switch (raw.grow(num_to_copy + raw.m_buf.meta.wi)) {
46189 case sync_io::DynIOBuffer::GrowResult::OK:
46190 break;
46191 case sync_io::DynIOBuffer::GrowResult::FailedMaxInclExceeded:
46192 return error_messages.resolve(
46193 error_messages.max_incl_metadata_length_exceeded);
46194 case sync_io::DynIOBuffer::GrowResult::FailedOutOfMemory:
46195 return error_messages.resolve(error_messages.out_of_memory);
46196 }
46197 }
46198
46199 if (io_buf.reader_position() > r.min_incl) {
46200 return error_messages.resolve(error_messages.unsupported_metadata);
46201 } else {
46202 std::string error_message =
46203 AdvanceIOBufferTo(error_messages, input, io_buf, r.min_incl);
46204 if (!error_message.empty()) {
46205 return error_message;
46206 }
46207 }
46208
46209 while (true) {
46210 uint64_t n =
46211 wuffs_base__u64__min(num_to_copy, io_buf.reader_length());
46212 memcpy(raw.m_buf.writer_pointer(), io_buf.reader_pointer(), n);
46213 raw.m_buf.meta.wi += n;
46214 io_buf.meta.ri += n;
46215 num_to_copy -= n;
46216 if (num_to_copy == 0) {
46217 break;
46218 } else if (io_buf.meta.closed) {
46219 return error_messages.resolve(
46220 error_messages.unexpected_end_of_file);
46221 } else if (!input.BringsItsOwnIOBuffer()) {
46222 io_buf.compact();
46223 }
46224 std::string error_message = input.CopyIn(&io_buf);
46225 if (!error_message.empty()) {
46226 return error_message;
46227 }
46228 }
46229 break;
46230 }
46231
46232 default:
46233 return error_messages.resolve(error_messages.unsupported_metadata);
46234 }
46235
46236 if (status.repr == nullptr) {
46237 break;
46238 } else if (status.repr != wuffs_base__suspension__even_more_information) {
46239 if (status.repr != wuffs_base__suspension__short_write) {
46240 return status.message();
46241 }
46242 switch (raw.grow(wuffs_base__u64__sat_add(raw.m_buf.data.len, 1))) {
46243 case sync_io::DynIOBuffer::GrowResult::OK:
46244 break;
46245 case sync_io::DynIOBuffer::GrowResult::FailedMaxInclExceeded:
46246 return error_messages.resolve(
46247 error_messages.max_incl_metadata_length_exceeded);
46248 case sync_io::DynIOBuffer::GrowResult::FailedOutOfMemory:
46249 return error_messages.resolve(error_messages.out_of_memory);
46250 }
46251 }
46252 }
46253
46254 return (*handle_metadata_func)(handle_metadata_receiver, &minfo,
46255 raw.m_buf.reader_slice());
46256}
46257
46258} // namespace private_impl
46259
Nigel Taoe360a532021-04-05 22:47:03 +100046260} // namespace wuffs_aux
46261
46262#endif // !defined(WUFFS_CONFIG__MODULES) ||
46263 // defined(WUFFS_CONFIG__MODULE__AUX__BASE)
46264
46265// ---------------- Auxiliary - CBOR
46266
46267#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
46268
46269#include <utility>
46270
46271namespace wuffs_aux {
46272
46273DecodeCborResult::DecodeCborResult(std::string&& error_message0,
46274 uint64_t cursor_position0)
46275 : error_message(std::move(error_message0)),
46276 cursor_position(cursor_position0) {}
46277
46278DecodeCborCallbacks::~DecodeCborCallbacks() {}
46279
46280void //
46281DecodeCborCallbacks::Done(DecodeCborResult& result,
46282 sync_io::Input& input,
46283 IOBuffer& buffer) {}
46284
Nigel Taobf9dab32021-11-18 19:19:55 +110046285DecodeCborArgQuirks::DecodeCborArgQuirks(wuffs_base__slice_u32 repr0)
46286 : repr(repr0) {}
46287
46288DecodeCborArgQuirks::DecodeCborArgQuirks(uint32_t* ptr0, size_t len0)
46289 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
46290
46291DecodeCborArgQuirks //
46292DecodeCborArgQuirks::DefaultValue() {
46293 return DecodeCborArgQuirks(wuffs_base__empty_slice_u32());
46294}
46295
Nigel Taoe360a532021-04-05 22:47:03 +100046296DecodeCborResult //
46297DecodeCbor(DecodeCborCallbacks& callbacks,
46298 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110046299 DecodeCborArgQuirks quirks) {
Nigel Taoe360a532021-04-05 22:47:03 +100046300 // Prepare the wuffs_base__io_buffer and the resultant error_message.
46301 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
46302 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
46303 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
46304 if (!io_buf) {
46305 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
46306 fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
46307 io_buf = &fallback_io_buf;
46308 }
46309 // cursor_index is discussed at
46310 // https://nigeltao.github.io/blog/2020/jsonptr.html#the-cursor-index
46311 size_t cursor_index = 0;
46312 std::string ret_error_message;
46313 std::string io_error_message;
46314
46315 do {
46316 // Prepare the low-level CBOR decoder.
46317 wuffs_cbor__decoder::unique_ptr dec = wuffs_cbor__decoder::alloc();
46318 if (!dec) {
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046319 ret_error_message = "wuffs_aux::DecodeCbor: out of memory";
Nigel Taoe360a532021-04-05 22:47:03 +100046320 goto done;
46321 }
Nigel Taobf9dab32021-11-18 19:19:55 +110046322 for (size_t i = 0; i < quirks.repr.len; i++) {
46323 dec->set_quirk_enabled(quirks.repr.ptr[i], true);
Nigel Taoe360a532021-04-05 22:47:03 +100046324 }
46325
46326 // Prepare the wuffs_base__tok_buffer. 256 tokens is 2KiB.
46327 wuffs_base__token tok_array[256];
46328 wuffs_base__token_buffer tok_buf =
46329 wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
46330 &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
46331 wuffs_base__status tok_status = wuffs_base__make_status(nullptr);
46332
46333 // Prepare other state.
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046334 int32_t depth = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100046335 std::string str;
46336 int64_t extension_category = 0;
46337 uint64_t extension_detail = 0;
46338
46339 // Valid token's VBCs range in 0 ..= 15. Values over that are for tokens
46340 // from outside of the base package, such as the CBOR package.
46341 constexpr int64_t EXT_CAT__CBOR_TAG = 16;
46342
46343 // Loop, doing these two things:
46344 // 1. Get the next token.
46345 // 2. Process that token.
46346 while (true) {
46347 // 1. Get the next token.
46348
46349 while (tok_buf.meta.ri >= tok_buf.meta.wi) {
46350 if (tok_status.repr == nullptr) {
46351 // No-op.
46352 } else if (tok_status.repr == wuffs_base__suspension__short_write) {
46353 tok_buf.compact();
46354 } else if (tok_status.repr == wuffs_base__suspension__short_read) {
46355 // Read from input to io_buf.
46356 if (!io_error_message.empty()) {
46357 ret_error_message = std::move(io_error_message);
46358 goto done;
46359 } else if (cursor_index != io_buf->meta.ri) {
46360 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046361 "wuffs_aux::DecodeCbor: internal error: bad cursor_index";
Nigel Taoe360a532021-04-05 22:47:03 +100046362 goto done;
46363 } else if (io_buf->meta.closed) {
46364 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046365 "wuffs_aux::DecodeCbor: internal error: io_buf is closed";
Nigel Taoe360a532021-04-05 22:47:03 +100046366 goto done;
46367 }
46368 io_buf->compact();
46369 if (io_buf->meta.wi >= io_buf->data.len) {
46370 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046371 "wuffs_aux::DecodeCbor: internal error: io_buf is full";
Nigel Taoe360a532021-04-05 22:47:03 +100046372 goto done;
46373 }
46374 cursor_index = io_buf->meta.ri;
46375 io_error_message = input.CopyIn(io_buf);
46376 } else {
46377 ret_error_message = tok_status.message();
46378 goto done;
46379 }
46380
46381 if (WUFFS_CBOR__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {
46382 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046383 "wuffs_aux::DecodeCbor: internal error: bad WORKBUF_LEN";
Nigel Taoe360a532021-04-05 22:47:03 +100046384 goto done;
46385 }
46386 wuffs_base__slice_u8 work_buf = wuffs_base__empty_slice_u8();
46387 tok_status = dec->decode_tokens(&tok_buf, io_buf, work_buf);
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046388 if ((tok_buf.meta.ri > tok_buf.meta.wi) ||
46389 (tok_buf.meta.wi > tok_buf.data.len) ||
46390 (io_buf->meta.ri > io_buf->meta.wi) ||
46391 (io_buf->meta.wi > io_buf->data.len)) {
46392 ret_error_message =
46393 "wuffs_aux::DecodeCbor: internal error: bad buffer indexes";
46394 goto done;
46395 }
Nigel Taoe360a532021-04-05 22:47:03 +100046396 }
46397
46398 wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++];
46399 uint64_t token_len = token.length();
46400 if ((io_buf->meta.ri < cursor_index) ||
46401 ((io_buf->meta.ri - cursor_index) < token_len)) {
46402 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046403 "wuffs_aux::DecodeCbor: internal error: bad token indexes";
Nigel Taoe360a532021-04-05 22:47:03 +100046404 goto done;
46405 }
46406 uint8_t* token_ptr = io_buf->data.ptr + cursor_index;
46407 cursor_index += static_cast<size_t>(token_len);
46408
46409 // 2. Process that token.
46410
46411 uint64_t vbd = token.value_base_detail();
46412
46413 if (extension_category != 0) {
46414 int64_t ext = token.value_extension();
46415 if ((ext >= 0) && !token.continued()) {
46416 extension_detail = (extension_detail
46417 << WUFFS_BASE__TOKEN__VALUE_EXTENSION__NUM_BITS) |
46418 static_cast<uint64_t>(ext);
46419 switch (extension_category) {
46420 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED:
46421 extension_category = 0;
46422 ret_error_message =
46423 callbacks.AppendI64(static_cast<int64_t>(extension_detail));
46424 goto parsed_a_value;
46425 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED:
46426 extension_category = 0;
46427 ret_error_message = callbacks.AppendU64(extension_detail);
46428 goto parsed_a_value;
46429 case EXT_CAT__CBOR_TAG:
46430 extension_category = 0;
46431 ret_error_message = callbacks.AppendCborTag(extension_detail);
46432 if (!ret_error_message.empty()) {
46433 goto done;
46434 }
46435 continue;
46436 }
46437 }
46438 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046439 "wuffs_aux::DecodeCbor: internal error: bad extended token";
Nigel Taoe360a532021-04-05 22:47:03 +100046440 goto done;
46441 }
46442
46443 switch (token.value_base_category()) {
46444 case WUFFS_BASE__TOKEN__VBC__FILLER:
46445 continue;
46446
46447 case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
46448 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
46449 ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
46450 if (!ret_error_message.empty()) {
46451 goto done;
46452 }
46453 depth++;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046454 if (depth > WUFFS_CBOR__DECODER_DEPTH_MAX_INCL) {
46455 ret_error_message =
46456 "wuffs_aux::DecodeCbor: internal error: bad depth";
46457 goto done;
46458 }
Nigel Taoe360a532021-04-05 22:47:03 +100046459 continue;
46460 }
46461 ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
46462 depth--;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046463 if (depth < 0) {
46464 ret_error_message =
46465 "wuffs_aux::DecodeCbor: internal error: bad depth";
46466 goto done;
46467 }
Nigel Taoe360a532021-04-05 22:47:03 +100046468 goto parsed_a_value;
46469 }
46470
46471 case WUFFS_BASE__TOKEN__VBC__STRING: {
46472 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
46473 // No-op.
46474 } else if (vbd &
46475 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
46476 const char* ptr = // Convert from (uint8_t*).
46477 static_cast<const char*>(static_cast<void*>(token_ptr));
46478 str.append(ptr, static_cast<size_t>(token_len));
46479 } else {
46480 goto fail;
46481 }
46482 if (token.continued()) {
46483 continue;
46484 }
46485 ret_error_message =
46486 (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CHAIN_MUST_BE_UTF_8)
46487 ? callbacks.AppendTextString(std::move(str))
46488 : callbacks.AppendByteString(std::move(str));
46489 str.clear();
46490 goto parsed_a_value;
46491 }
46492
46493 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
46494 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
46495 size_t n = wuffs_base__utf_8__encode(
46496 wuffs_base__make_slice_u8(
46497 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
46498 static_cast<uint32_t>(vbd));
46499 const char* ptr = // Convert from (uint8_t*).
46500 static_cast<const char*>(static_cast<void*>(&u[0]));
46501 str.append(ptr, n);
46502 if (token.continued()) {
46503 continue;
46504 }
46505 goto fail;
46506 }
46507
46508 case WUFFS_BASE__TOKEN__VBC__LITERAL: {
46509 if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL) {
46510 ret_error_message = callbacks.AppendNull();
46511 } else if (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__UNDEFINED) {
46512 ret_error_message = callbacks.AppendUndefined();
46513 } else {
46514 ret_error_message = callbacks.AppendBool(
46515 vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
46516 }
46517 goto parsed_a_value;
46518 }
46519
46520 case WUFFS_BASE__TOKEN__VBC__NUMBER: {
46521 const uint64_t cfp_fbbe_fifb =
46522 WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT |
46523 WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_BINARY_BIG_ENDIAN |
46524 WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_IGNORE_FIRST_BYTE;
46525 if ((vbd & cfp_fbbe_fifb) == cfp_fbbe_fifb) {
46526 double f;
46527 switch (token_len) {
46528 case 3:
46529 f = wuffs_base__ieee_754_bit_representation__from_u16_to_f64(
46530 wuffs_base__peek_u16be__no_bounds_check(token_ptr + 1));
46531 break;
46532 case 5:
46533 f = wuffs_base__ieee_754_bit_representation__from_u32_to_f64(
46534 wuffs_base__peek_u32be__no_bounds_check(token_ptr + 1));
46535 break;
46536 case 9:
46537 f = wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
46538 wuffs_base__peek_u64be__no_bounds_check(token_ptr + 1));
46539 break;
46540 default:
46541 goto fail;
46542 }
46543 ret_error_message = callbacks.AppendF64(f);
46544 goto parsed_a_value;
46545 }
46546 goto fail;
46547 }
46548
46549 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED: {
46550 if (token.continued()) {
46551 extension_category = WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_SIGNED;
46552 extension_detail =
46553 static_cast<uint64_t>(token.value_base_detail__sign_extended());
46554 continue;
46555 }
46556 ret_error_message =
46557 callbacks.AppendI64(token.value_base_detail__sign_extended());
46558 goto parsed_a_value;
46559 }
46560
46561 case WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED: {
46562 if (token.continued()) {
46563 extension_category =
46564 WUFFS_BASE__TOKEN__VBC__INLINE_INTEGER_UNSIGNED;
46565 extension_detail = vbd;
46566 continue;
46567 }
46568 ret_error_message = callbacks.AppendU64(vbd);
46569 goto parsed_a_value;
46570 }
46571 }
46572
46573 if (token.value_major() == WUFFS_CBOR__TOKEN_VALUE_MAJOR) {
46574 uint64_t value_minor = token.value_minor();
46575 if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__MINUS_1_MINUS_X) {
46576 if (token_len == 9) {
46577 ret_error_message = callbacks.AppendMinus1MinusX(
46578 wuffs_base__peek_u64be__no_bounds_check(token_ptr + 1));
46579 goto parsed_a_value;
46580 }
46581 } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__SIMPLE_VALUE) {
46582 ret_error_message =
46583 callbacks.AppendCborSimpleValue(static_cast<uint8_t>(
46584 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK));
46585 goto parsed_a_value;
46586 } else if (value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__TAG) {
46587 if (token.continued()) {
46588 extension_category = EXT_CAT__CBOR_TAG;
46589 extension_detail =
46590 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK;
46591 continue;
46592 }
46593 ret_error_message = callbacks.AppendCborTag(
46594 value_minor & WUFFS_CBOR__TOKEN_VALUE_MINOR__DETAIL_MASK);
46595 if (!ret_error_message.empty()) {
46596 goto done;
46597 }
46598 continue;
46599 }
46600 }
46601
46602 fail:
46603 ret_error_message =
Nigel Taoc9d2ed72021-08-15 13:50:22 +100046604 "wuffs_aux::DecodeCbor: internal error: unexpected token";
Nigel Taoe360a532021-04-05 22:47:03 +100046605 goto done;
46606
46607 parsed_a_value:
46608 if (!ret_error_message.empty() || (depth == 0)) {
46609 goto done;
46610 }
46611 }
46612 } while (false);
46613
46614done:
46615 DecodeCborResult result(
46616 std::move(ret_error_message),
46617 wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
46618 callbacks.Done(result, input, *io_buf);
46619 return result;
46620}
46621
46622} // namespace wuffs_aux
46623
46624#endif // !defined(WUFFS_CONFIG__MODULES) ||
46625 // defined(WUFFS_CONFIG__MODULE__AUX__CBOR)
46626
46627// ---------------- Auxiliary - Image
46628
46629#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__IMAGE)
46630
46631#include <utility>
46632
46633namespace wuffs_aux {
46634
46635DecodeImageResult::DecodeImageResult(MemOwner&& pixbuf_mem_owner0,
46636 wuffs_base__pixel_buffer pixbuf0,
46637 std::string&& error_message0)
46638 : pixbuf_mem_owner(std::move(pixbuf_mem_owner0)),
46639 pixbuf(pixbuf0),
46640 error_message(std::move(error_message0)) {}
46641
46642DecodeImageResult::DecodeImageResult(std::string&& error_message0)
46643 : pixbuf_mem_owner(nullptr, &free),
46644 pixbuf(wuffs_base__null_pixel_buffer()),
46645 error_message(std::move(error_message0)) {}
46646
46647DecodeImageCallbacks::~DecodeImageCallbacks() {}
46648
46649DecodeImageCallbacks::AllocPixbufResult::AllocPixbufResult(
46650 MemOwner&& mem_owner0,
46651 wuffs_base__pixel_buffer pixbuf0)
46652 : mem_owner(std::move(mem_owner0)), pixbuf(pixbuf0), error_message("") {}
46653
46654DecodeImageCallbacks::AllocPixbufResult::AllocPixbufResult(
46655 std::string&& error_message0)
46656 : mem_owner(nullptr, &free),
46657 pixbuf(wuffs_base__null_pixel_buffer()),
46658 error_message(std::move(error_message0)) {}
46659
46660DecodeImageCallbacks::AllocWorkbufResult::AllocWorkbufResult(
46661 MemOwner&& mem_owner0,
46662 wuffs_base__slice_u8 workbuf0)
46663 : mem_owner(std::move(mem_owner0)), workbuf(workbuf0), error_message("") {}
46664
46665DecodeImageCallbacks::AllocWorkbufResult::AllocWorkbufResult(
46666 std::string&& error_message0)
46667 : mem_owner(nullptr, &free),
46668 workbuf(wuffs_base__empty_slice_u8()),
46669 error_message(std::move(error_message0)) {}
46670
46671wuffs_base__image_decoder::unique_ptr //
46672DecodeImageCallbacks::SelectDecoder(uint32_t fourcc,
Nigel Taocc74cb42022-01-19 11:06:15 +110046673 wuffs_base__slice_u8 prefix_data,
46674 bool prefix_closed) {
Nigel Taoe360a532021-04-05 22:47:03 +100046675 switch (fourcc) {
46676#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BMP)
46677 case WUFFS_BASE__FOURCC__BMP:
46678 return wuffs_bmp__decoder::alloc_as__wuffs_base__image_decoder();
46679#endif
46680
46681#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__GIF)
46682 case WUFFS_BASE__FOURCC__GIF:
46683 return wuffs_gif__decoder::alloc_as__wuffs_base__image_decoder();
46684#endif
46685
46686#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__NIE)
46687 case WUFFS_BASE__FOURCC__NIE:
46688 return wuffs_nie__decoder::alloc_as__wuffs_base__image_decoder();
46689#endif
46690
46691#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__PNG)
46692 case WUFFS_BASE__FOURCC__PNG: {
46693 auto dec = wuffs_png__decoder::alloc_as__wuffs_base__image_decoder();
46694 // Favor faster decodes over rejecting invalid checksums.
46695 dec->set_quirk_enabled(WUFFS_BASE__QUIRK_IGNORE_CHECKSUM, true);
46696 return dec;
46697 }
46698#endif
46699
Nigel Taocc74cb42022-01-19 11:06:15 +110046700#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__TGA)
46701 case WUFFS_BASE__FOURCC__TGA:
46702 return wuffs_tga__decoder::alloc_as__wuffs_base__image_decoder();
46703#endif
46704
Nigel Taoe360a532021-04-05 22:47:03 +100046705#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__WBMP)
46706 case WUFFS_BASE__FOURCC__WBMP:
46707 return wuffs_wbmp__decoder::alloc_as__wuffs_base__image_decoder();
46708#endif
46709 }
46710
46711 return wuffs_base__image_decoder::unique_ptr(nullptr, &free);
46712}
46713
Nigel Taobf9dab32021-11-18 19:19:55 +110046714std::string //
46715DecodeImageCallbacks::HandleMetadata(const wuffs_base__more_information& minfo,
46716 wuffs_base__slice_u8 raw) {
46717 return "";
46718}
46719
Nigel Taoe360a532021-04-05 22:47:03 +100046720wuffs_base__pixel_format //
46721DecodeImageCallbacks::SelectPixfmt(
46722 const wuffs_base__image_config& image_config) {
46723 return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL);
46724}
46725
46726DecodeImageCallbacks::AllocPixbufResult //
46727DecodeImageCallbacks::AllocPixbuf(const wuffs_base__image_config& image_config,
46728 bool allow_uninitialized_memory) {
46729 uint32_t w = image_config.pixcfg.width();
46730 uint32_t h = image_config.pixcfg.height();
46731 if ((w == 0) || (h == 0)) {
46732 return AllocPixbufResult("");
46733 }
46734 uint64_t len = image_config.pixcfg.pixbuf_len();
46735 if ((len == 0) || (SIZE_MAX < len)) {
46736 return AllocPixbufResult(DecodeImage_UnsupportedPixelConfiguration);
46737 }
46738 void* ptr =
46739 allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1);
46740 if (!ptr) {
46741 return AllocPixbufResult(DecodeImage_OutOfMemory);
46742 }
46743 wuffs_base__pixel_buffer pixbuf;
46744 wuffs_base__status status = pixbuf.set_from_slice(
46745 &image_config.pixcfg,
46746 wuffs_base__make_slice_u8((uint8_t*)ptr, (size_t)len));
46747 if (!status.is_ok()) {
46748 free(ptr);
46749 return AllocPixbufResult(status.message());
46750 }
46751 return AllocPixbufResult(MemOwner(ptr, &free), pixbuf);
46752}
46753
46754DecodeImageCallbacks::AllocWorkbufResult //
46755DecodeImageCallbacks::AllocWorkbuf(wuffs_base__range_ii_u64 len_range,
46756 bool allow_uninitialized_memory) {
46757 uint64_t len = len_range.max_incl;
46758 if (len == 0) {
46759 return AllocWorkbufResult("");
46760 } else if (SIZE_MAX < len) {
46761 return AllocWorkbufResult(DecodeImage_OutOfMemory);
46762 }
46763 void* ptr =
46764 allow_uninitialized_memory ? malloc((size_t)len) : calloc((size_t)len, 1);
46765 if (!ptr) {
46766 return AllocWorkbufResult(DecodeImage_OutOfMemory);
46767 }
46768 return AllocWorkbufResult(
46769 MemOwner(ptr, &free),
46770 wuffs_base__make_slice_u8((uint8_t*)ptr, (size_t)len));
46771}
46772
46773void //
46774DecodeImageCallbacks::Done(
46775 DecodeImageResult& result,
46776 sync_io::Input& input,
46777 IOBuffer& buffer,
46778 wuffs_base__image_decoder::unique_ptr image_decoder) {}
46779
46780const char DecodeImage_BufferIsTooShort[] = //
46781 "wuffs_aux::DecodeImage: buffer is too short";
46782const char DecodeImage_MaxInclDimensionExceeded[] = //
46783 "wuffs_aux::DecodeImage: max_incl_dimension exceeded";
Nigel Taobf9dab32021-11-18 19:19:55 +110046784const char DecodeImage_MaxInclMetadataLengthExceeded[] = //
46785 "wuffs_aux::DecodeImage: max_incl_metadata_length exceeded";
Nigel Taoe360a532021-04-05 22:47:03 +100046786const char DecodeImage_OutOfMemory[] = //
46787 "wuffs_aux::DecodeImage: out of memory";
46788const char DecodeImage_UnexpectedEndOfFile[] = //
46789 "wuffs_aux::DecodeImage: unexpected end of file";
46790const char DecodeImage_UnsupportedImageFormat[] = //
46791 "wuffs_aux::DecodeImage: unsupported image format";
Nigel Taobf9dab32021-11-18 19:19:55 +110046792const char DecodeImage_UnsupportedMetadata[] = //
46793 "wuffs_aux::DecodeImage: unsupported metadata";
Nigel Taoe360a532021-04-05 22:47:03 +100046794const char DecodeImage_UnsupportedPixelBlend[] = //
46795 "wuffs_aux::DecodeImage: unsupported pixel blend";
46796const char DecodeImage_UnsupportedPixelConfiguration[] = //
46797 "wuffs_aux::DecodeImage: unsupported pixel configuration";
46798const char DecodeImage_UnsupportedPixelFormat[] = //
46799 "wuffs_aux::DecodeImage: unsupported pixel format";
46800
Nigel Taobf9dab32021-11-18 19:19:55 +110046801DecodeImageArgQuirks::DecodeImageArgQuirks(wuffs_base__slice_u32 repr0)
46802 : repr(repr0) {}
46803
46804DecodeImageArgQuirks::DecodeImageArgQuirks(uint32_t* ptr0, size_t len0)
46805 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
46806
46807DecodeImageArgQuirks //
46808DecodeImageArgQuirks::DefaultValue() {
46809 return DecodeImageArgQuirks(wuffs_base__empty_slice_u32());
46810}
46811
46812DecodeImageArgFlags::DecodeImageArgFlags(uint64_t repr0) : repr(repr0) {}
46813
46814DecodeImageArgFlags //
46815DecodeImageArgFlags::DefaultValue() {
46816 return DecodeImageArgFlags(0);
46817}
46818
46819DecodeImageArgPixelBlend::DecodeImageArgPixelBlend(
46820 wuffs_base__pixel_blend repr0)
46821 : repr(repr0) {}
46822
46823DecodeImageArgPixelBlend //
46824DecodeImageArgPixelBlend::DefaultValue() {
46825 return DecodeImageArgPixelBlend(WUFFS_BASE__PIXEL_BLEND__SRC);
46826}
46827
46828DecodeImageArgBackgroundColor::DecodeImageArgBackgroundColor(
46829 wuffs_base__color_u32_argb_premul repr0)
46830 : repr(repr0) {}
46831
46832DecodeImageArgBackgroundColor //
46833DecodeImageArgBackgroundColor::DefaultValue() {
46834 return DecodeImageArgBackgroundColor(1);
46835}
46836
46837DecodeImageArgMaxInclDimension::DecodeImageArgMaxInclDimension(uint32_t repr0)
46838 : repr(repr0) {}
46839
46840DecodeImageArgMaxInclDimension //
46841DecodeImageArgMaxInclDimension::DefaultValue() {
46842 return DecodeImageArgMaxInclDimension(1048575);
46843}
46844
46845DecodeImageArgMaxInclMetadataLength::DecodeImageArgMaxInclMetadataLength(
46846 uint64_t repr0)
46847 : repr(repr0) {}
46848
46849DecodeImageArgMaxInclMetadataLength //
46850DecodeImageArgMaxInclMetadataLength::DefaultValue() {
46851 return DecodeImageArgMaxInclMetadataLength(16777215);
46852}
46853
Nigel Taoe360a532021-04-05 22:47:03 +100046854// --------
46855
46856namespace {
46857
Nigel Taobf9dab32021-11-18 19:19:55 +110046858const private_impl::ErrorMessages DecodeImageErrorMessages = {
46859 DecodeImage_MaxInclMetadataLengthExceeded, //
46860 DecodeImage_OutOfMemory, //
46861 DecodeImage_UnexpectedEndOfFile, //
46862 DecodeImage_UnsupportedMetadata, //
46863 DecodeImage_UnsupportedImageFormat, //
46864};
46865
Nigel Taoe360a532021-04-05 22:47:03 +100046866std::string //
Nigel Taobf9dab32021-11-18 19:19:55 +110046867DecodeImageAdvanceIOBufferTo(sync_io::Input& input,
46868 wuffs_base__io_buffer& io_buf,
46869 uint64_t absolute_position) {
46870 return private_impl::AdvanceIOBufferTo(DecodeImageErrorMessages, input,
46871 io_buf, absolute_position);
46872}
46873
46874wuffs_base__status //
46875DIHM0(void* self,
46876 wuffs_base__io_buffer* a_dst,
46877 wuffs_base__more_information* a_minfo,
46878 wuffs_base__io_buffer* a_src) {
46879 return wuffs_base__image_decoder__tell_me_more(
46880 static_cast<wuffs_base__image_decoder*>(self), a_dst, a_minfo, a_src);
46881}
46882
46883std::string //
46884DIHM1(void* self,
46885 const wuffs_base__more_information* minfo,
46886 wuffs_base__slice_u8 raw) {
46887 return static_cast<DecodeImageCallbacks*>(self)->HandleMetadata(*minfo, raw);
46888}
46889
46890std::string //
46891DecodeImageHandleMetadata(wuffs_base__image_decoder::unique_ptr& image_decoder,
46892 DecodeImageCallbacks& callbacks,
46893 sync_io::Input& input,
46894 wuffs_base__io_buffer& io_buf,
46895 sync_io::DynIOBuffer& raw_metadata_buf) {
46896 return private_impl::HandleMetadata(DecodeImageErrorMessages, input, io_buf,
46897 raw_metadata_buf, DIHM0,
46898 static_cast<void*>(image_decoder.get()),
46899 DIHM1, static_cast<void*>(&callbacks));
Nigel Taoe360a532021-04-05 22:47:03 +100046900}
46901
46902DecodeImageResult //
46903DecodeImage0(wuffs_base__image_decoder::unique_ptr& image_decoder,
46904 DecodeImageCallbacks& callbacks,
46905 sync_io::Input& input,
46906 wuffs_base__io_buffer& io_buf,
Nigel Taobf9dab32021-11-18 19:19:55 +110046907 wuffs_base__slice_u32 quirks,
46908 uint64_t flags,
Nigel Taoe360a532021-04-05 22:47:03 +100046909 wuffs_base__pixel_blend pixel_blend,
46910 wuffs_base__color_u32_argb_premul background_color,
Nigel Taobf9dab32021-11-18 19:19:55 +110046911 uint32_t max_incl_dimension,
46912 uint64_t max_incl_metadata_length) {
Nigel Taoe360a532021-04-05 22:47:03 +100046913 // Check args.
46914 switch (pixel_blend) {
46915 case WUFFS_BASE__PIXEL_BLEND__SRC:
46916 case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:
46917 break;
46918 default:
46919 return DecodeImageResult(DecodeImage_UnsupportedPixelBlend);
46920 }
46921
46922 wuffs_base__image_config image_config = wuffs_base__null_image_config();
Nigel Taobf9dab32021-11-18 19:19:55 +110046923 sync_io::DynIOBuffer raw_metadata_buf(max_incl_metadata_length);
Nigel Taoe360a532021-04-05 22:47:03 +100046924 uint64_t start_pos = io_buf.reader_position();
Nigel Tao123a5c62022-06-03 14:17:20 +100046925 bool interested_in_metadata_after_the_frame = false;
Nigel Taoe360a532021-04-05 22:47:03 +100046926 bool redirected = false;
46927 int32_t fourcc = 0;
46928redirect:
46929 do {
46930 // Determine the image format.
46931 if (!redirected) {
46932 while (true) {
Nigel Taocc74cb42022-01-19 11:06:15 +110046933 fourcc = wuffs_base__magic_number_guess_fourcc(io_buf.reader_slice(),
46934 io_buf.meta.closed);
Nigel Taoe360a532021-04-05 22:47:03 +100046935 if (fourcc > 0) {
46936 break;
46937 } else if ((fourcc == 0) && (io_buf.reader_length() >= 64)) {
Nigel Taocc74cb42022-01-19 11:06:15 +110046938 // Having (fourcc == 0) means that Wuffs' built in MIME sniffer
46939 // didn't recognize the image format. Nonetheless, custom callbacks
46940 // may still be able to do their own MIME sniffing, for exotic image
46941 // types. We try to give them at least 64 bytes of prefix data when
46942 // one-shot-calling callbacks.SelectDecoder. There is no mechanism
46943 // for the callbacks to request a longer prefix.
Nigel Taoe360a532021-04-05 22:47:03 +100046944 break;
46945 } else if (io_buf.meta.closed || (io_buf.writer_length() == 0)) {
46946 fourcc = 0;
46947 break;
46948 }
46949 std::string error_message = input.CopyIn(&io_buf);
46950 if (!error_message.empty()) {
46951 return DecodeImageResult(std::move(error_message));
46952 }
46953 }
46954 } else {
46955 wuffs_base__io_buffer empty = wuffs_base__empty_io_buffer();
46956 wuffs_base__more_information minfo = wuffs_base__empty_more_information();
46957 wuffs_base__status tmm_status =
46958 image_decoder->tell_me_more(&empty, &minfo, &io_buf);
46959 if (tmm_status.repr != nullptr) {
46960 return DecodeImageResult(tmm_status.message());
46961 }
46962 if (minfo.flavor != WUFFS_BASE__MORE_INFORMATION__FLAVOR__IO_REDIRECT) {
46963 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
46964 }
46965 uint64_t pos = minfo.io_redirect__range().min_incl;
Nigel Taobf9dab32021-11-18 19:19:55 +110046966 if (pos <= start_pos) {
46967 // Redirects must go forward.
46968 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
46969 }
46970 std::string error_message =
46971 DecodeImageAdvanceIOBufferTo(input, io_buf, pos);
Nigel Taoe360a532021-04-05 22:47:03 +100046972 if (!error_message.empty()) {
46973 return DecodeImageResult(std::move(error_message));
46974 }
46975 fourcc = (int32_t)(minfo.io_redirect__fourcc());
46976 if (fourcc == 0) {
46977 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
46978 }
46979 image_decoder.reset();
46980 }
46981
46982 // Select the image decoder.
46983 image_decoder = callbacks.SelectDecoder(
Nigel Taocc74cb42022-01-19 11:06:15 +110046984 (uint32_t)fourcc, io_buf.reader_slice(), io_buf.meta.closed);
Nigel Taoe360a532021-04-05 22:47:03 +100046985 if (!image_decoder) {
46986 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
46987 }
46988
Nigel Taobf9dab32021-11-18 19:19:55 +110046989 // Apply quirks.
46990 for (size_t i = 0; i < quirks.len; i++) {
46991 image_decoder->set_quirk_enabled(quirks.ptr[i], true);
46992 }
46993
46994 // Apply flags.
46995 if (flags != 0) {
46996 if (flags & DecodeImageArgFlags::REPORT_METADATA_CHRM) {
46997 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__CHRM, true);
46998 }
Nigel Taoebbecaa2022-01-08 14:08:27 +110046999 if (flags & DecodeImageArgFlags::REPORT_METADATA_EXIF) {
Nigel Tao123a5c62022-06-03 14:17:20 +100047000 interested_in_metadata_after_the_frame = true;
Nigel Taoebbecaa2022-01-08 14:08:27 +110047001 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__EXIF, true);
47002 }
Nigel Taobf9dab32021-11-18 19:19:55 +110047003 if (flags & DecodeImageArgFlags::REPORT_METADATA_GAMA) {
47004 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__GAMA, true);
47005 }
47006 if (flags & DecodeImageArgFlags::REPORT_METADATA_ICCP) {
47007 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__ICCP, true);
47008 }
47009 if (flags & DecodeImageArgFlags::REPORT_METADATA_KVP) {
Nigel Tao123a5c62022-06-03 14:17:20 +100047010 interested_in_metadata_after_the_frame = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110047011 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__KVP, true);
47012 }
47013 if (flags & DecodeImageArgFlags::REPORT_METADATA_SRGB) {
47014 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__SRGB, true);
47015 }
47016 if (flags & DecodeImageArgFlags::REPORT_METADATA_XMP) {
Nigel Tao123a5c62022-06-03 14:17:20 +100047017 interested_in_metadata_after_the_frame = true;
Nigel Taobf9dab32021-11-18 19:19:55 +110047018 image_decoder->set_report_metadata(WUFFS_BASE__FOURCC__XMP, true);
47019 }
47020 }
47021
Nigel Taoe360a532021-04-05 22:47:03 +100047022 // Decode the image config.
47023 while (true) {
47024 wuffs_base__status id_dic_status =
47025 image_decoder->decode_image_config(&image_config, &io_buf);
47026 if (id_dic_status.repr == nullptr) {
47027 break;
47028 } else if (id_dic_status.repr == wuffs_base__note__i_o_redirect) {
47029 if (redirected) {
47030 return DecodeImageResult(DecodeImage_UnsupportedImageFormat);
47031 }
47032 redirected = true;
47033 goto redirect;
Nigel Taobf9dab32021-11-18 19:19:55 +110047034 } else if (id_dic_status.repr == wuffs_base__note__metadata_reported) {
47035 std::string error_message = DecodeImageHandleMetadata(
47036 image_decoder, callbacks, input, io_buf, raw_metadata_buf);
47037 if (!error_message.empty()) {
47038 return DecodeImageResult(std::move(error_message));
47039 }
Nigel Taoe360a532021-04-05 22:47:03 +100047040 } else if (id_dic_status.repr != wuffs_base__suspension__short_read) {
47041 return DecodeImageResult(id_dic_status.message());
47042 } else if (io_buf.meta.closed) {
47043 return DecodeImageResult(DecodeImage_UnexpectedEndOfFile);
47044 } else {
47045 std::string error_message = input.CopyIn(&io_buf);
47046 if (!error_message.empty()) {
47047 return DecodeImageResult(std::move(error_message));
47048 }
47049 }
47050 }
47051 } while (false);
Nigel Tao123a5c62022-06-03 14:17:20 +100047052 if (!interested_in_metadata_after_the_frame) {
47053 raw_metadata_buf.drop();
47054 }
Nigel Taoe360a532021-04-05 22:47:03 +100047055
47056 // Select the pixel format.
47057 uint32_t w = image_config.pixcfg.width();
47058 uint32_t h = image_config.pixcfg.height();
47059 if ((w > max_incl_dimension) || (h > max_incl_dimension)) {
47060 return DecodeImageResult(DecodeImage_MaxInclDimensionExceeded);
47061 }
47062 wuffs_base__pixel_format pixel_format = callbacks.SelectPixfmt(image_config);
47063 if (pixel_format.repr != image_config.pixcfg.pixel_format().repr) {
47064 switch (pixel_format.repr) {
47065 case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
47066 case WUFFS_BASE__PIXEL_FORMAT__BGR:
47067 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
47068 case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:
47069 case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
47070 case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
47071 case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
47072 break;
47073 default:
47074 return DecodeImageResult(DecodeImage_UnsupportedPixelFormat);
47075 }
47076 image_config.pixcfg.set(pixel_format.repr,
47077 WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, w, h);
47078 }
47079
47080 // Allocate the pixel buffer.
47081 bool valid_background_color =
47082 wuffs_base__color_u32_argb_premul__is_valid(background_color);
47083 DecodeImageCallbacks::AllocPixbufResult alloc_pixbuf_result =
47084 callbacks.AllocPixbuf(image_config, valid_background_color);
47085 if (!alloc_pixbuf_result.error_message.empty()) {
47086 return DecodeImageResult(std::move(alloc_pixbuf_result.error_message));
47087 }
47088 wuffs_base__pixel_buffer pixel_buffer = alloc_pixbuf_result.pixbuf;
47089 if (valid_background_color) {
47090 wuffs_base__status pb_scufr_status = pixel_buffer.set_color_u32_fill_rect(
47091 pixel_buffer.pixcfg.bounds(), background_color);
47092 if (pb_scufr_status.repr != nullptr) {
47093 return DecodeImageResult(pb_scufr_status.message());
47094 }
47095 }
47096
47097 // Allocate the work buffer. Wuffs' decoders conventionally assume that this
47098 // can be uninitialized memory.
47099 wuffs_base__range_ii_u64 workbuf_len = image_decoder->workbuf_len();
47100 DecodeImageCallbacks::AllocWorkbufResult alloc_workbuf_result =
47101 callbacks.AllocWorkbuf(workbuf_len, true);
47102 if (!alloc_workbuf_result.error_message.empty()) {
47103 return DecodeImageResult(std::move(alloc_workbuf_result.error_message));
47104 } else if (alloc_workbuf_result.workbuf.len < workbuf_len.min_incl) {
47105 return DecodeImageResult(DecodeImage_BufferIsTooShort);
47106 }
47107
47108 // Decode the frame config.
47109 wuffs_base__frame_config frame_config = wuffs_base__null_frame_config();
47110 while (true) {
47111 wuffs_base__status id_dfc_status =
47112 image_decoder->decode_frame_config(&frame_config, &io_buf);
47113 if (id_dfc_status.repr == nullptr) {
47114 break;
Nigel Tao123a5c62022-06-03 14:17:20 +100047115 } else if (id_dfc_status.repr == wuffs_base__note__metadata_reported) {
47116 std::string error_message = DecodeImageHandleMetadata(
47117 image_decoder, callbacks, input, io_buf, raw_metadata_buf);
47118 if (!error_message.empty()) {
47119 return DecodeImageResult(std::move(error_message));
47120 }
Nigel Taoe360a532021-04-05 22:47:03 +100047121 } else if (id_dfc_status.repr != wuffs_base__suspension__short_read) {
47122 return DecodeImageResult(id_dfc_status.message());
47123 } else if (io_buf.meta.closed) {
47124 return DecodeImageResult(DecodeImage_UnexpectedEndOfFile);
47125 } else {
47126 std::string error_message = input.CopyIn(&io_buf);
47127 if (!error_message.empty()) {
47128 return DecodeImageResult(std::move(error_message));
47129 }
47130 }
47131 }
47132
47133 // Decode the frame (the pixels).
47134 //
47135 // From here on, always returns the pixel_buffer. If we get this far, we can
47136 // still display a partial image, even if we encounter an error.
47137 std::string message("");
47138 if ((pixel_blend == WUFFS_BASE__PIXEL_BLEND__SRC_OVER) &&
47139 frame_config.overwrite_instead_of_blend()) {
47140 pixel_blend = WUFFS_BASE__PIXEL_BLEND__SRC;
47141 }
47142 while (true) {
47143 wuffs_base__status id_df_status =
47144 image_decoder->decode_frame(&pixel_buffer, &io_buf, pixel_blend,
47145 alloc_workbuf_result.workbuf, nullptr);
47146 if (id_df_status.repr == nullptr) {
47147 break;
47148 } else if (id_df_status.repr != wuffs_base__suspension__short_read) {
47149 message = id_df_status.message();
47150 break;
47151 } else if (io_buf.meta.closed) {
47152 message = DecodeImage_UnexpectedEndOfFile;
47153 break;
47154 } else {
47155 std::string error_message = input.CopyIn(&io_buf);
47156 if (!error_message.empty()) {
47157 message = std::move(error_message);
47158 break;
47159 }
47160 }
47161 }
Nigel Tao123a5c62022-06-03 14:17:20 +100047162
47163 // Decode any metadata after the frame.
47164 if (interested_in_metadata_after_the_frame) {
47165 while (true) {
47166 wuffs_base__status id_dfc_status =
47167 image_decoder->decode_frame_config(NULL, &io_buf);
47168 if (id_dfc_status.repr == wuffs_base__note__end_of_data) {
47169 break;
47170 } else if (id_dfc_status.repr == nullptr) {
47171 continue;
47172 } else if (id_dfc_status.repr == wuffs_base__note__metadata_reported) {
47173 std::string error_message = DecodeImageHandleMetadata(
47174 image_decoder, callbacks, input, io_buf, raw_metadata_buf);
47175 if (!error_message.empty()) {
47176 return DecodeImageResult(std::move(error_message));
47177 }
47178 } else if (id_dfc_status.repr != wuffs_base__suspension__short_read) {
47179 return DecodeImageResult(id_dfc_status.message());
47180 } else if (io_buf.meta.closed) {
47181 return DecodeImageResult(DecodeImage_UnexpectedEndOfFile);
47182 } else {
47183 std::string error_message = input.CopyIn(&io_buf);
47184 if (!error_message.empty()) {
47185 return DecodeImageResult(std::move(error_message));
47186 }
47187 }
47188 }
47189 }
47190
Nigel Taoe360a532021-04-05 22:47:03 +100047191 return DecodeImageResult(std::move(alloc_pixbuf_result.mem_owner),
47192 pixel_buffer, std::move(message));
47193}
47194
47195} // namespace
47196
47197DecodeImageResult //
47198DecodeImage(DecodeImageCallbacks& callbacks,
47199 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110047200 DecodeImageArgQuirks quirks,
47201 DecodeImageArgFlags flags,
47202 DecodeImageArgPixelBlend pixel_blend,
47203 DecodeImageArgBackgroundColor background_color,
47204 DecodeImageArgMaxInclDimension max_incl_dimension,
47205 DecodeImageArgMaxInclMetadataLength max_incl_metadata_length) {
Nigel Taoe360a532021-04-05 22:47:03 +100047206 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
47207 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
47208 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
47209 if (!io_buf) {
47210 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[32768]);
47211 fallback_io_buf =
47212 wuffs_base__ptr_u8__writer(fallback_io_array.get(), 32768);
47213 io_buf = &fallback_io_buf;
47214 }
47215
47216 wuffs_base__image_decoder::unique_ptr image_decoder(nullptr, &free);
47217 DecodeImageResult result =
Nigel Taobf9dab32021-11-18 19:19:55 +110047218 DecodeImage0(image_decoder, callbacks, input, *io_buf, quirks.repr,
47219 flags.repr, pixel_blend.repr, background_color.repr,
47220 max_incl_dimension.repr, max_incl_metadata_length.repr);
Nigel Taoe360a532021-04-05 22:47:03 +100047221 callbacks.Done(result, input, *io_buf, std::move(image_decoder));
47222 return result;
47223}
47224
47225} // namespace wuffs_aux
47226
47227#endif // !defined(WUFFS_CONFIG__MODULES) ||
47228 // defined(WUFFS_CONFIG__MODULE__AUX__IMAGE)
47229
47230// ---------------- Auxiliary - JSON
47231
47232#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__AUX__JSON)
47233
47234#include <utility>
47235
47236namespace wuffs_aux {
47237
47238DecodeJsonResult::DecodeJsonResult(std::string&& error_message0,
47239 uint64_t cursor_position0)
47240 : error_message(std::move(error_message0)),
47241 cursor_position(cursor_position0) {}
47242
47243DecodeJsonCallbacks::~DecodeJsonCallbacks() {}
47244
47245void //
47246DecodeJsonCallbacks::Done(DecodeJsonResult& result,
47247 sync_io::Input& input,
47248 IOBuffer& buffer) {}
47249
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047250const char DecodeJson_BadJsonPointer[] = //
Nigel Taoe360a532021-04-05 22:47:03 +100047251 "wuffs_aux::DecodeJson: bad JSON Pointer";
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047252const char DecodeJson_NoMatch[] = //
47253 "wuffs_aux::DecodeJson: no match";
Nigel Taoe360a532021-04-05 22:47:03 +100047254
Nigel Taobf9dab32021-11-18 19:19:55 +110047255DecodeJsonArgQuirks::DecodeJsonArgQuirks(wuffs_base__slice_u32 repr0)
47256 : repr(repr0) {}
47257
47258DecodeJsonArgQuirks::DecodeJsonArgQuirks(uint32_t* ptr0, size_t len0)
47259 : repr(wuffs_base__make_slice_u32(ptr0, len0)) {}
47260
47261DecodeJsonArgQuirks //
47262DecodeJsonArgQuirks::DefaultValue() {
47263 return DecodeJsonArgQuirks(wuffs_base__empty_slice_u32());
47264}
47265
47266DecodeJsonArgJsonPointer::DecodeJsonArgJsonPointer(std::string repr0)
47267 : repr(repr0) {}
47268
47269DecodeJsonArgJsonPointer //
47270DecodeJsonArgJsonPointer::DefaultValue() {
47271 return DecodeJsonArgJsonPointer(std::string());
47272}
47273
Nigel Taoe360a532021-04-05 22:47:03 +100047274// --------
47275
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047276#define WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN \
47277 while (tok_buf.meta.ri >= tok_buf.meta.wi) { \
47278 if (tok_status.repr == nullptr) { \
47279 goto done; \
47280 } else if (tok_status.repr == wuffs_base__suspension__short_write) { \
47281 tok_buf.compact(); \
47282 } else if (tok_status.repr == wuffs_base__suspension__short_read) { \
47283 if (!io_error_message.empty()) { \
47284 ret_error_message = std::move(io_error_message); \
47285 goto done; \
47286 } else if (cursor_index != io_buf->meta.ri) { \
47287 ret_error_message = \
47288 "wuffs_aux::DecodeJson: internal error: bad cursor_index"; \
47289 goto done; \
47290 } else if (io_buf->meta.closed) { \
47291 ret_error_message = \
47292 "wuffs_aux::DecodeJson: internal error: io_buf is closed"; \
47293 goto done; \
47294 } \
47295 io_buf->compact(); \
47296 if (io_buf->meta.wi >= io_buf->data.len) { \
47297 ret_error_message = \
47298 "wuffs_aux::DecodeJson: internal error: io_buf is full"; \
47299 goto done; \
47300 } \
47301 cursor_index = io_buf->meta.ri; \
47302 io_error_message = input.CopyIn(io_buf); \
47303 } else { \
47304 ret_error_message = tok_status.message(); \
47305 goto done; \
47306 } \
47307 tok_status = \
47308 dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8()); \
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047309 if ((tok_buf.meta.ri > tok_buf.meta.wi) || \
47310 (tok_buf.meta.wi > tok_buf.data.len) || \
47311 (io_buf->meta.ri > io_buf->meta.wi) || \
47312 (io_buf->meta.wi > io_buf->data.len)) { \
47313 ret_error_message = \
47314 "wuffs_aux::DecodeJson: internal error: bad buffer indexes"; \
47315 goto done; \
47316 } \
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047317 } \
47318 wuffs_base__token token = tok_buf.data.ptr[tok_buf.meta.ri++]; \
47319 uint64_t token_len = token.length(); \
47320 if ((io_buf->meta.ri < cursor_index) || \
47321 ((io_buf->meta.ri - cursor_index) < token_len)) { \
47322 ret_error_message = \
47323 "wuffs_aux::DecodeJson: internal error: bad token indexes"; \
47324 goto done; \
47325 } \
47326 uint8_t* token_ptr = io_buf->data.ptr + cursor_index; \
47327 (void)(token_ptr); \
Nigel Taoe360a532021-04-05 22:47:03 +100047328 cursor_index += static_cast<size_t>(token_len)
47329
47330// --------
47331
47332namespace {
47333
47334// DecodeJson_SplitJsonPointer returns ("bar", 8) for ("/foo/bar/b~1z/qux", 5,
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047335// etc). It returns a 0 size_t when s has invalid JSON Pointer syntax or i is
47336// out of bounds.
Nigel Taoe360a532021-04-05 22:47:03 +100047337//
47338// The string returned is unescaped. If calling it again, this time with i=8,
47339// the "b~1z" substring would be returned as "b/z".
47340std::pair<std::string, size_t> //
47341DecodeJson_SplitJsonPointer(std::string& s,
47342 size_t i,
47343 bool allow_tilde_n_tilde_r_tilde_t) {
47344 std::string fragment;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047345 if (i > s.size()) {
47346 return std::make_pair(std::string(), 0);
47347 }
Nigel Taoe360a532021-04-05 22:47:03 +100047348 while (i < s.size()) {
47349 char c = s[i];
47350 if (c == '/') {
47351 break;
47352 } else if (c != '~') {
47353 fragment.push_back(c);
47354 i++;
47355 continue;
47356 }
47357 i++;
47358 if (i >= s.size()) {
47359 return std::make_pair(std::string(), 0);
47360 }
47361 c = s[i];
47362 if (c == '0') {
47363 fragment.push_back('~');
47364 i++;
47365 continue;
47366 } else if (c == '1') {
47367 fragment.push_back('/');
47368 i++;
47369 continue;
47370 } else if (allow_tilde_n_tilde_r_tilde_t) {
47371 if (c == 'n') {
47372 fragment.push_back('\n');
47373 i++;
47374 continue;
47375 } else if (c == 'r') {
47376 fragment.push_back('\r');
47377 i++;
47378 continue;
47379 } else if (c == 't') {
47380 fragment.push_back('\t');
47381 i++;
47382 continue;
47383 }
47384 }
47385 return std::make_pair(std::string(), 0);
47386 }
47387 return std::make_pair(std::move(fragment), i);
47388}
47389
47390// --------
47391
47392std::string //
47393DecodeJson_WalkJsonPointerFragment(wuffs_base__token_buffer& tok_buf,
47394 wuffs_base__status& tok_status,
47395 wuffs_json__decoder::unique_ptr& dec,
47396 wuffs_base__io_buffer* io_buf,
47397 std::string& io_error_message,
47398 size_t& cursor_index,
47399 sync_io::Input& input,
47400 std::string& json_pointer_fragment) {
47401 std::string ret_error_message;
47402 while (true) {
47403 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47404
47405 int64_t vbc = token.value_base_category();
47406 uint64_t vbd = token.value_base_detail();
47407 if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
47408 continue;
47409 } else if ((vbc != WUFFS_BASE__TOKEN__VBC__STRUCTURE) ||
47410 !(vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH)) {
47411 return DecodeJson_NoMatch;
47412 } else if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__TO_LIST) {
47413 goto do_list;
47414 }
47415 goto do_dict;
47416 }
47417
47418do_dict:
47419 // Alternate between these two things:
47420 // 1. Decode the next dict key (a string). If it matches the fragment, we're
47421 // done (success). If we've reached the dict's end (VBD__STRUCTURE__POP)
47422 // so that there was no next dict key, we're done (failure).
47423 // 2. Otherwise, skip the next dict value.
47424 while (true) {
47425 for (std::string str; true;) {
47426 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47427
47428 int64_t vbc = token.value_base_category();
47429 uint64_t vbd = token.value_base_detail();
47430 switch (vbc) {
47431 case WUFFS_BASE__TOKEN__VBC__FILLER:
47432 continue;
47433
47434 case WUFFS_BASE__TOKEN__VBC__STRUCTURE:
47435 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
47436 goto fail;
47437 }
47438 return DecodeJson_NoMatch;
47439
47440 case WUFFS_BASE__TOKEN__VBC__STRING: {
47441 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
47442 // No-op.
47443 } else if (vbd &
47444 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
47445 const char* ptr = // Convert from (uint8_t*).
47446 static_cast<const char*>(static_cast<void*>(token_ptr));
47447 str.append(ptr, static_cast<size_t>(token_len));
47448 } else {
47449 goto fail;
47450 }
47451 break;
47452 }
47453
47454 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
47455 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
47456 size_t n = wuffs_base__utf_8__encode(
47457 wuffs_base__make_slice_u8(
47458 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
47459 static_cast<uint32_t>(vbd));
47460 const char* ptr = // Convert from (uint8_t*).
47461 static_cast<const char*>(static_cast<void*>(&u[0]));
47462 str.append(ptr, n);
47463 break;
47464 }
47465
47466 default:
47467 goto fail;
47468 }
47469
47470 if (token.continued()) {
47471 continue;
47472 }
47473 if (str == json_pointer_fragment) {
47474 return "";
47475 }
47476 goto skip_the_next_dict_value;
47477 }
47478
47479 skip_the_next_dict_value:
47480 for (uint32_t skip_depth = 0; true;) {
47481 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47482
47483 int64_t vbc = token.value_base_category();
47484 uint64_t vbd = token.value_base_detail();
47485 if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
47486 continue;
47487 } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
47488 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
47489 skip_depth++;
47490 continue;
47491 }
47492 skip_depth--;
47493 }
47494
47495 if (skip_depth == 0) {
47496 break;
47497 }
47498 } // skip_the_next_dict_value
47499 } // do_dict
47500
47501do_list:
47502 do {
47503 wuffs_base__result_u64 result_u64 = wuffs_base__parse_number_u64(
47504 wuffs_base__make_slice_u8(
47505 static_cast<uint8_t*>(static_cast<void*>(
47506 const_cast<char*>(json_pointer_fragment.data()))),
47507 json_pointer_fragment.size()),
47508 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
47509 if (!result_u64.status.is_ok()) {
47510 return DecodeJson_NoMatch;
47511 }
47512 uint64_t remaining = result_u64.value;
47513 if (remaining == 0) {
47514 goto check_that_a_value_follows;
47515 }
47516 for (uint32_t skip_depth = 0; true;) {
47517 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47518
47519 int64_t vbc = token.value_base_category();
47520 uint64_t vbd = token.value_base_detail();
47521 if (token.continued() || (vbc == WUFFS_BASE__TOKEN__VBC__FILLER)) {
47522 continue;
47523 } else if (vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) {
47524 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
47525 skip_depth++;
47526 continue;
47527 }
47528 if (skip_depth == 0) {
47529 return DecodeJson_NoMatch;
47530 }
47531 skip_depth--;
47532 }
47533
47534 if (skip_depth > 0) {
47535 continue;
47536 }
47537 remaining--;
47538 if (remaining == 0) {
47539 goto check_that_a_value_follows;
47540 }
47541 }
47542 } while (false); // do_list
47543
47544check_that_a_value_follows:
47545 while (true) {
47546 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47547
47548 int64_t vbc = token.value_base_category();
47549 uint64_t vbd = token.value_base_detail();
47550 if (vbc == WUFFS_BASE__TOKEN__VBC__FILLER) {
47551 continue;
47552 }
47553
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047554 // Undo the last part of WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN, so
47555 // that we're only peeking at the next token.
Nigel Taoe360a532021-04-05 22:47:03 +100047556 tok_buf.meta.ri--;
47557 cursor_index -= static_cast<size_t>(token_len);
47558
47559 if ((vbc == WUFFS_BASE__TOKEN__VBC__STRUCTURE) &&
47560 (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__POP)) {
47561 return DecodeJson_NoMatch;
47562 }
47563 return "";
47564 } // check_that_a_value_follows
47565
47566fail:
47567 return "wuffs_aux::DecodeJson: internal error: unexpected token";
47568done:
47569 return ret_error_message;
47570}
47571
47572} // namespace
47573
47574// --------
47575
47576DecodeJsonResult //
47577DecodeJson(DecodeJsonCallbacks& callbacks,
47578 sync_io::Input& input,
Nigel Taobf9dab32021-11-18 19:19:55 +110047579 DecodeJsonArgQuirks quirks,
47580 DecodeJsonArgJsonPointer json_pointer) {
Nigel Taoe360a532021-04-05 22:47:03 +100047581 // Prepare the wuffs_base__io_buffer and the resultant error_message.
47582 wuffs_base__io_buffer* io_buf = input.BringsItsOwnIOBuffer();
47583 wuffs_base__io_buffer fallback_io_buf = wuffs_base__empty_io_buffer();
47584 std::unique_ptr<uint8_t[]> fallback_io_array(nullptr);
47585 if (!io_buf) {
47586 fallback_io_array = std::unique_ptr<uint8_t[]>(new uint8_t[4096]);
47587 fallback_io_buf = wuffs_base__ptr_u8__writer(fallback_io_array.get(), 4096);
47588 io_buf = &fallback_io_buf;
47589 }
47590 // cursor_index is discussed at
47591 // https://nigeltao.github.io/blog/2020/jsonptr.html#the-cursor-index
47592 size_t cursor_index = 0;
47593 std::string ret_error_message;
47594 std::string io_error_message;
47595
47596 do {
47597 // Prepare the low-level JSON decoder.
47598 wuffs_json__decoder::unique_ptr dec = wuffs_json__decoder::alloc();
47599 if (!dec) {
47600 ret_error_message = "wuffs_aux::DecodeJson: out of memory";
47601 goto done;
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047602 } else if (WUFFS_JSON__DECODER_WORKBUF_LEN_MAX_INCL_WORST_CASE != 0) {
47603 ret_error_message =
47604 "wuffs_aux::DecodeJson: internal error: bad WORKBUF_LEN";
47605 goto done;
Nigel Taoe360a532021-04-05 22:47:03 +100047606 }
47607 bool allow_tilde_n_tilde_r_tilde_t = false;
Nigel Taobf9dab32021-11-18 19:19:55 +110047608 for (size_t i = 0; i < quirks.repr.len; i++) {
47609 dec->set_quirk_enabled(quirks.repr.ptr[i], true);
47610 if (quirks.repr.ptr[i] ==
Nigel Taoe360a532021-04-05 22:47:03 +100047611 WUFFS_JSON__QUIRK_JSON_POINTER_ALLOW_TILDE_N_TILDE_R_TILDE_T) {
47612 allow_tilde_n_tilde_r_tilde_t = true;
47613 }
47614 }
47615
47616 // Prepare the wuffs_base__tok_buffer. 256 tokens is 2KiB.
47617 wuffs_base__token tok_array[256];
47618 wuffs_base__token_buffer tok_buf =
47619 wuffs_base__slice_token__writer(wuffs_base__make_slice_token(
47620 &tok_array[0], (sizeof(tok_array) / sizeof(tok_array[0]))));
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047621 wuffs_base__status tok_status =
47622 dec->decode_tokens(&tok_buf, io_buf, wuffs_base__empty_slice_u8());
Nigel Taoe360a532021-04-05 22:47:03 +100047623
47624 // Prepare other state.
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047625 int32_t depth = 0;
Nigel Taoe360a532021-04-05 22:47:03 +100047626 std::string str;
47627
47628 // Walk the (optional) JSON Pointer.
Nigel Taobf9dab32021-11-18 19:19:55 +110047629 for (size_t i = 0; i < json_pointer.repr.size();) {
47630 if (json_pointer.repr[i] != '/') {
Nigel Taoe360a532021-04-05 22:47:03 +100047631 ret_error_message = DecodeJson_BadJsonPointer;
47632 goto done;
47633 }
47634 std::pair<std::string, size_t> split = DecodeJson_SplitJsonPointer(
Nigel Taobf9dab32021-11-18 19:19:55 +110047635 json_pointer.repr, i + 1, allow_tilde_n_tilde_r_tilde_t);
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047636 i = split.second;
Nigel Taoe360a532021-04-05 22:47:03 +100047637 if (i == 0) {
47638 ret_error_message = DecodeJson_BadJsonPointer;
47639 goto done;
47640 }
47641 ret_error_message = DecodeJson_WalkJsonPointerFragment(
47642 tok_buf, tok_status, dec, io_buf, io_error_message, cursor_index,
47643 input, split.first);
47644 if (!ret_error_message.empty()) {
47645 goto done;
47646 }
47647 }
47648
47649 // Loop, doing these two things:
47650 // 1. Get the next token.
47651 // 2. Process that token.
47652 while (true) {
47653 WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN;
47654
47655 int64_t vbc = token.value_base_category();
47656 uint64_t vbd = token.value_base_detail();
47657 switch (vbc) {
47658 case WUFFS_BASE__TOKEN__VBC__FILLER:
47659 continue;
47660
47661 case WUFFS_BASE__TOKEN__VBC__STRUCTURE: {
47662 if (vbd & WUFFS_BASE__TOKEN__VBD__STRUCTURE__PUSH) {
47663 ret_error_message = callbacks.Push(static_cast<uint32_t>(vbd));
47664 if (!ret_error_message.empty()) {
47665 goto done;
47666 }
47667 depth++;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047668 if (depth > WUFFS_JSON__DECODER_DEPTH_MAX_INCL) {
47669 ret_error_message =
47670 "wuffs_aux::DecodeJson: internal error: bad depth";
47671 goto done;
47672 }
Nigel Taoe360a532021-04-05 22:47:03 +100047673 continue;
47674 }
47675 ret_error_message = callbacks.Pop(static_cast<uint32_t>(vbd));
47676 depth--;
Nigel Taoc9d2ed72021-08-15 13:50:22 +100047677 if (depth < 0) {
47678 ret_error_message =
47679 "wuffs_aux::DecodeJson: internal error: bad depth";
47680 goto done;
47681 }
Nigel Taoe360a532021-04-05 22:47:03 +100047682 goto parsed_a_value;
47683 }
47684
47685 case WUFFS_BASE__TOKEN__VBC__STRING: {
47686 if (vbd & WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_0_DST_1_SRC_DROP) {
47687 // No-op.
47688 } else if (vbd &
47689 WUFFS_BASE__TOKEN__VBD__STRING__CONVERT_1_DST_1_SRC_COPY) {
47690 const char* ptr = // Convert from (uint8_t*).
47691 static_cast<const char*>(static_cast<void*>(token_ptr));
47692 str.append(ptr, static_cast<size_t>(token_len));
47693 } else {
47694 goto fail;
47695 }
47696 if (token.continued()) {
47697 continue;
47698 }
47699 ret_error_message = callbacks.AppendTextString(std::move(str));
47700 str.clear();
47701 goto parsed_a_value;
47702 }
47703
47704 case WUFFS_BASE__TOKEN__VBC__UNICODE_CODE_POINT: {
47705 uint8_t u[WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL];
47706 size_t n = wuffs_base__utf_8__encode(
47707 wuffs_base__make_slice_u8(
47708 &u[0], WUFFS_BASE__UTF_8__BYTE_LENGTH__MAX_INCL),
47709 static_cast<uint32_t>(vbd));
47710 const char* ptr = // Convert from (uint8_t*).
47711 static_cast<const char*>(static_cast<void*>(&u[0]));
47712 str.append(ptr, n);
47713 if (token.continued()) {
47714 continue;
47715 }
47716 goto fail;
47717 }
47718
47719 case WUFFS_BASE__TOKEN__VBC__LITERAL: {
47720 ret_error_message =
47721 (vbd & WUFFS_BASE__TOKEN__VBD__LITERAL__NULL)
47722 ? callbacks.AppendNull()
47723 : callbacks.AppendBool(vbd &
47724 WUFFS_BASE__TOKEN__VBD__LITERAL__TRUE);
47725 goto parsed_a_value;
47726 }
47727
47728 case WUFFS_BASE__TOKEN__VBC__NUMBER: {
47729 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__FORMAT_TEXT) {
47730 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_INTEGER_SIGNED) {
47731 wuffs_base__result_i64 r = wuffs_base__parse_number_i64(
47732 wuffs_base__make_slice_u8(token_ptr,
47733 static_cast<size_t>(token_len)),
47734 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
47735 if (r.status.is_ok()) {
47736 ret_error_message = callbacks.AppendI64(r.value);
47737 goto parsed_a_value;
47738 }
47739 }
47740 if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_FLOATING_POINT) {
47741 wuffs_base__result_f64 r = wuffs_base__parse_number_f64(
47742 wuffs_base__make_slice_u8(token_ptr,
47743 static_cast<size_t>(token_len)),
47744 WUFFS_BASE__PARSE_NUMBER_XXX__DEFAULT_OPTIONS);
47745 if (r.status.is_ok()) {
47746 ret_error_message = callbacks.AppendF64(r.value);
47747 goto parsed_a_value;
47748 }
47749 }
47750 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_INF) {
47751 ret_error_message = callbacks.AppendF64(
47752 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
47753 0xFFF0000000000000ul));
47754 goto parsed_a_value;
47755 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_INF) {
47756 ret_error_message = callbacks.AppendF64(
47757 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
47758 0x7FF0000000000000ul));
47759 goto parsed_a_value;
47760 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_NEG_NAN) {
47761 ret_error_message = callbacks.AppendF64(
47762 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
47763 0xFFFFFFFFFFFFFFFFul));
47764 goto parsed_a_value;
47765 } else if (vbd & WUFFS_BASE__TOKEN__VBD__NUMBER__CONTENT_POS_NAN) {
47766 ret_error_message = callbacks.AppendF64(
47767 wuffs_base__ieee_754_bit_representation__from_u64_to_f64(
47768 0x7FFFFFFFFFFFFFFFul));
47769 goto parsed_a_value;
47770 }
47771 goto fail;
47772 }
47773 }
47774
47775 fail:
47776 ret_error_message =
47777 "wuffs_aux::DecodeJson: internal error: unexpected token";
47778 goto done;
47779
47780 parsed_a_value:
Nigel Taod5b8cfa2021-07-18 11:37:27 +100047781 // If an error was encountered, we are done. Otherwise, (depth == 0)
47782 // after parsing a value is equivalent to having decoded the entire JSON
47783 // value (for an empty json_pointer query) or having decoded the
47784 // pointed-to JSON value (for a non-empty json_pointer query). In the
47785 // latter case, we are also done.
47786 //
47787 // However, if quirks like WUFFS_JSON__QUIRK_ALLOW_TRAILING_FILLER or
47788 // WUFFS_JSON__QUIRK_EXPECT_TRAILING_NEW_LINE_OR_EOF are passed, decoding
47789 // the entire JSON value should also consume any trailing filler, in case
47790 // the DecodeJson caller wants to subsequently check that the input is
47791 // completely exhausted (and otherwise raise "valid JSON followed by
47792 // further (unexpected) data"). We aren't done yet. Instead, keep the
47793 // loop running until WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN's
47794 // decode_tokens returns an ok status.
47795 if (!ret_error_message.empty() ||
Nigel Taobf9dab32021-11-18 19:19:55 +110047796 ((depth == 0) && !json_pointer.repr.empty())) {
Nigel Taoe360a532021-04-05 22:47:03 +100047797 goto done;
47798 }
47799 }
47800 } while (false);
47801
47802done:
47803 DecodeJsonResult result(
47804 std::move(ret_error_message),
47805 wuffs_base__u64__sat_add(io_buf->meta.pos, cursor_index));
47806 callbacks.Done(result, input, *io_buf);
47807 return result;
47808}
47809
47810#undef WUFFS_AUX__DECODE_JSON__GET_THE_NEXT_TOKEN
47811
47812} // namespace wuffs_aux
47813
47814#endif // !defined(WUFFS_CONFIG__MODULES) ||
47815 // defined(WUFFS_CONFIG__MODULE__AUX__JSON)
47816
47817#endif // defined(__cplusplus) && defined(WUFFS_BASE__HAVE_UNIQUE_PTR)
47818
47819#endif // WUFFS_IMPLEMENTATION
47820
47821#if defined(__GNUC__)
47822#pragma GCC diagnostic pop
Nigel Taobb778712021-06-25 15:38:45 +100047823#elif defined(__clang__)
47824#pragma clang diagnostic pop
Nigel Taoe360a532021-04-05 22:47:03 +100047825#endif
47826
47827#endif // WUFFS_INCLUDE_GUARD