| #ifndef PUFFS_FLATE_H |
| #define PUFFS_FLATE_H |
| |
| // Code generated by puffs-c. DO NOT EDIT. |
| |
| #ifndef PUFFS_BASE_HEADER_H |
| #define PUFFS_BASE_HEADER_H |
| |
| // Copyright 2017 The Puffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <string.h> |
| |
| // Puffs requires a word size of at least 32 bits because it assumes that |
| // converting a u32 to usize will never overflow. For example, the size of a |
| // decoded image is often represented, explicitly or implicitly in an image |
| // file, as a u32, and it is convenient to compare that to a buffer size. |
| // |
| // Similarly, the word size is at most 64 bits because it assumes that |
| // converting a usize to u64 will never overflow. |
| #if __WORDSIZE < 32 |
| #error "Puffs requires a word size of at least 32 bits" |
| #elif __WORDSIZE > 64 |
| #error "Puffs requires a word size of at most 64 bits" |
| #endif |
| |
| // PUFFS_VERSION is the major.minor version number as a uint32. The major |
| // number is the high 16 bits. The minor number is the low 16 bits. |
| // |
| // The intention is to bump the version number at least on every API / ABI |
| // backwards incompatible change. |
| // |
| // For now, the API and ABI are simply unstable and can change at any time. |
| // |
| // TODO: don't hard code this in base-header.h. |
| #define PUFFS_VERSION (0x00001) |
| |
| // puffs_base__slice_u8 is a 1-dimensional buffer (a pointer and length). |
| // |
| // A value with all fields NULL or zero is a valid, empty slice. |
| typedef struct { |
| uint8_t* ptr; |
| size_t len; |
| } puffs_base__slice_u8; |
| |
| // puffs_base__buf1 is a 1-dimensional buffer (a pointer and length), plus |
| // additional indexes into that buffer, plus an opened / closed flag. |
| // |
| // A value with all fields NULL or zero is a valid, empty buffer. |
| typedef struct { |
| uint8_t* ptr; // Pointer. |
| size_t len; // Length. |
| size_t wi; // Write index. Invariant: wi <= len. |
| size_t ri; // Read index. Invariant: ri <= wi. |
| bool closed; // No further writes are expected. |
| } puffs_base__buf1; |
| |
| // puffs_base__limit1 provides a limited view of a 1-dimensional byte stream: |
| // its first N bytes. That N can be greater than a buffer's current read or |
| // write capacity. N decreases naturally over time as bytes are read from or |
| // written to the stream. |
| // |
| // A value with all fields NULL or zero is a valid, unlimited view. |
| typedef struct puffs_base__limit1 { |
| uint64_t* ptr_to_len; // Pointer to N. |
| struct puffs_base__limit1* next; // Linked list of limits. |
| } puffs_base__limit1; |
| |
| typedef struct { |
| puffs_base__buf1* buf; |
| puffs_base__limit1 limit; |
| } puffs_base__reader1; |
| |
| typedef struct { |
| puffs_base__buf1* buf; |
| puffs_base__limit1 limit; |
| } puffs_base__writer1; |
| |
| #endif // PUFFS_BASE_HEADER_H |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| // ---------------- Status Codes |
| |
| // Status codes are int32_t values: |
| // - the sign bit indicates a non-recoverable status code: an error |
| // - bits 10-30 hold the packageid: a namespace |
| // - bits 8-9 are reserved |
| // - bits 0-7 are a package-namespaced numeric code |
| // |
| // Do not manipulate these bits directly. Use the API functions such as |
| // puffs_flate__status__is_error instead. |
| typedef int32_t puffs_flate__status; |
| |
| #define puffs_flate__packageid 967230 // 0x000ec23e |
| |
| #define PUFFS_FLATE__STATUS_OK 0 // 0x00000000 |
| #define PUFFS_FLATE__ERROR_BAD_PUFFS_VERSION -2147483647 // 0x80000001 |
| #define PUFFS_FLATE__ERROR_BAD_RECEIVER -2147483646 // 0x80000002 |
| #define PUFFS_FLATE__ERROR_BAD_ARGUMENT -2147483645 // 0x80000003 |
| #define PUFFS_FLATE__ERROR_INITIALIZER_NOT_CALLED -2147483644 // 0x80000004 |
| #define PUFFS_FLATE__ERROR_CLOSED_FOR_WRITES -2147483643 // 0x80000005 |
| #define PUFFS_FLATE__ERROR_UNEXPECTED_EOF -2147483642 // 0x80000006 |
| #define PUFFS_FLATE__SUSPENSION_SHORT_READ 7 // 0x00000007 |
| #define PUFFS_FLATE__SUSPENSION_SHORT_WRITE 8 // 0x00000008 |
| |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_OVER_SUBSCRIBED \ |
| -1157040128 // 0xbb08f800 |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_UNDER_SUBSCRIBED \ |
| -1157040127 // 0xbb08f801 |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT \ |
| -1157040126 // 0xbb08f802 |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_REPETITION \ |
| -1157040125 // 0xbb08f803 |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE -1157040124 // 0xbb08f804 |
| #define PUFFS_FLATE__ERROR_BAD_HUFFMAN_MINIMUM_CODE_LENGTH \ |
| -1157040123 // 0xbb08f805 |
| #define PUFFS_FLATE__ERROR_BAD_DISTANCE -1157040122 // 0xbb08f806 |
| #define PUFFS_FLATE__ERROR_BAD_DISTANCE_CODE_COUNT -1157040121 // 0xbb08f807 |
| #define PUFFS_FLATE__ERROR_BAD_FLATE_BLOCK -1157040120 // 0xbb08f808 |
| #define PUFFS_FLATE__ERROR_BAD_LITERAL_LENGTH_CODE_COUNT \ |
| -1157040119 // 0xbb08f809 |
| #define PUFFS_FLATE__ERROR_CHECKSUM_MISMATCH -1157040118 // 0xbb08f80a |
| #define PUFFS_FLATE__ERROR_INCONSISTENT_STORED_BLOCK_LENGTH \ |
| -1157040117 // 0xbb08f80b |
| #define PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE \ |
| -1157040116 // 0xbb08f80c |
| #define PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS \ |
| -1157040115 // 0xbb08f80d |
| #define PUFFS_FLATE__ERROR_MISSING_END_OF_BLOCK_CODE -1157040114 // 0xbb08f80e |
| #define PUFFS_FLATE__ERROR_NO_HUFFMAN_CODES -1157040113 // 0xbb08f80f |
| #define PUFFS_FLATE__ERROR_INVALID_ZLIB_COMPRESSION_METHOD \ |
| -1157040112 // 0xbb08f810 |
| #define PUFFS_FLATE__ERROR_INVALID_ZLIB_COMPRESSION_WINDOW_SIZE \ |
| -1157040111 // 0xbb08f811 |
| #define PUFFS_FLATE__ERROR_INVALID_ZLIB_PARITY_CHECK -1157040110 // 0xbb08f812 |
| #define PUFFS_FLATE__ERROR_TODO_UNSUPPORTED_ZLIB_PRESET_DICTIONARY \ |
| -1157040109 // 0xbb08f813 |
| |
| bool puffs_flate__status__is_error(puffs_flate__status s); |
| |
| const char* puffs_flate__status__string(puffs_flate__status s); |
| |
| // ---------------- Public Consts |
| |
| // ---------------- Structs |
| |
| typedef struct { |
| // Do not access the private_impl's fields directly. There is no API/ABI |
| // compatibility or safety guarantee if you do so. Instead, use the |
| // puffs_flate__flate_decoder__etc functions. |
| // |
| // In C++, these fields would be "private", but C does not support that. |
| // |
| // It is a struct, not a struct*, so that it can be stack allocated. |
| struct { |
| puffs_flate__status status; |
| uint32_t magic; |
| |
| uint32_t f_bits; |
| uint32_t f_n_bits; |
| uint32_t f_huffs[2][1234]; |
| uint32_t f_n_huffs_bits[2]; |
| uint8_t f_history[32768]; |
| uint32_t f_history_index; |
| uint8_t f_code_lengths[320]; |
| |
| struct { |
| uint32_t coro_susp_point; |
| puffs_flate__status v_z; |
| uint64_t v_n_copied; |
| uint32_t v_already_full; |
| } c_decode[1]; |
| struct { |
| uint32_t coro_susp_point; |
| uint32_t v_final; |
| uint32_t v_type; |
| } c_decode_blocks[1]; |
| struct { |
| uint32_t coro_susp_point; |
| uint32_t v_length; |
| uint32_t v_n_copied; |
| uint64_t scratch; |
| } c_decode_uncompressed[1]; |
| struct { |
| uint32_t coro_susp_point; |
| uint32_t v_bits; |
| uint32_t v_n_bits; |
| uint32_t v_table_entry; |
| uint32_t v_table_entry_n_bits; |
| uint32_t v_lmask; |
| uint32_t v_dmask; |
| uint32_t v_redir_top; |
| uint32_t v_redir_mask; |
| uint32_t v_length; |
| uint32_t v_distance; |
| uint32_t v_n_copied; |
| uint32_t v_hlen; |
| uint32_t v_hdist; |
| } c_decode_huffman[1]; |
| struct { |
| uint32_t coro_susp_point; |
| uint32_t v_i; |
| } c_init_fixed_huffman[1]; |
| struct { |
| uint32_t coro_susp_point; |
| uint32_t v_bits; |
| uint32_t v_n_bits; |
| uint32_t v_n_lit; |
| uint32_t v_n_dist; |
| uint32_t v_n_clen; |
| uint32_t v_i; |
| uint32_t v_mask; |
| uint32_t v_table_entry; |
| uint32_t v_table_entry_n_bits; |
| uint32_t v_n_extra_bits; |
| uint8_t v_rep_symbol; |
| uint32_t v_rep_count; |
| } c_init_dynamic_huffman[1]; |
| } private_impl; |
| } puffs_flate__flate_decoder; |
| |
| typedef struct { |
| // Do not access the private_impl's fields directly. There is no API/ABI |
| // compatibility or safety guarantee if you do so. Instead, use the |
| // puffs_flate__adler32__etc functions. |
| // |
| // In C++, these fields would be "private", but C does not support that. |
| // |
| // It is a struct, not a struct*, so that it can be stack allocated. |
| struct { |
| puffs_flate__status status; |
| uint32_t magic; |
| |
| uint32_t f_state; |
| |
| } private_impl; |
| } puffs_flate__adler32; |
| |
| typedef struct { |
| // Do not access the private_impl's fields directly. There is no API/ABI |
| // compatibility or safety guarantee if you do so. Instead, use the |
| // puffs_flate__zlib_decoder__etc functions. |
| // |
| // In C++, these fields would be "private", but C does not support that. |
| // |
| // It is a struct, not a struct*, so that it can be stack allocated. |
| struct { |
| puffs_flate__status status; |
| uint32_t magic; |
| |
| puffs_flate__flate_decoder f_flate; |
| puffs_flate__adler32 f_adler; |
| |
| struct { |
| uint32_t coro_susp_point; |
| uint16_t v_x; |
| uint32_t v_checksum; |
| puffs_flate__status v_z; |
| uint64_t scratch; |
| } c_decode[1]; |
| } private_impl; |
| } puffs_flate__zlib_decoder; |
| |
| // ---------------- Public Initializer Prototypes |
| |
| // puffs_flate__flate_decoder__initialize is an initializer function. |
| // |
| // It should be called before any other puffs_flate__flate_decoder__* function. |
| // |
| // Pass PUFFS_VERSION and 0 for puffs_version and for_internal_use_only. |
| void puffs_flate__flate_decoder__initialize(puffs_flate__flate_decoder* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only); |
| |
| // puffs_flate__zlib_decoder__initialize is an initializer function. |
| // |
| // It should be called before any other puffs_flate__zlib_decoder__* function. |
| // |
| // Pass PUFFS_VERSION and 0 for puffs_version and for_internal_use_only. |
| void puffs_flate__zlib_decoder__initialize(puffs_flate__zlib_decoder* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only); |
| |
| // ---------------- Public Function Prototypes |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src); |
| |
| puffs_flate__status puffs_flate__zlib_decoder__decode( |
| puffs_flate__zlib_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src); |
| |
| #ifdef __cplusplus |
| } // extern "C" |
| #endif |
| |
| #endif // PUFFS_FLATE_H |
| |
| // C HEADER ENDS HERE. |
| |
| #ifndef PUFFS_BASE_IMPL_H |
| #define PUFFS_BASE_IMPL_H |
| |
| // Copyright 2017 The Puffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // https://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #define PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(x) (void)(x) |
| |
| // PUFFS_BASE__MAGIC is a magic number to check that initializers are called. |
| // It's not foolproof, given C doesn't automatically zero memory before use, |
| // but it should catch 99.99% of cases. |
| // |
| // Its (non-zero) value is arbitrary, based on md5sum("puffs"). |
| #define PUFFS_BASE__MAGIC (0xCB3699CCU) |
| |
| // PUFFS_BASE__ALREADY_ZEROED is passed from a container struct's initializer |
| // to a containee struct's initializer when the container has already zeroed |
| // the containee's memory. |
| // |
| // Its (non-zero) value is arbitrary, based on md5sum("zeroed"). |
| #define PUFFS_BASE__ALREADY_ZEROED (0x68602EF1U) |
| |
| // Use switch cases for coroutine suspension points, similar to the technique |
| // in https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html |
| // |
| // We use a trivial macro instead of an explicit assignment and case statement |
| // so that clang-format doesn't get confused by the unusual "case"s. |
| #define PUFFS_BASE__COROUTINE_SUSPENSION_POINT(n) \ |
| coro_susp_point = n; \ |
| case n:; |
| |
| #define PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(n) \ |
| if (status < 0) { \ |
| goto exit; \ |
| } else if (status == 0) { \ |
| goto ok; \ |
| } \ |
| coro_susp_point = n; \ |
| goto suspend; \ |
| case n:; |
| |
| // Clang also defines "__GNUC__". |
| #if defined(__GNUC__) |
| #define PUFFS_BASE__LIKELY(expr) (__builtin_expect(!!(expr), 1)) |
| #define PUFFS_BASE__UNLIKELY(expr) (__builtin_expect(!!(expr), 0)) |
| // Declare the printf prototype. The generated code shouldn't need this at all, |
| // but it's useful for manual printf debugging. |
| extern int printf(const char* __restrict __format, ...); |
| #else |
| #define PUFFS_BASE__LIKELY(expr) (expr) |
| #define PUFFS_BASE__UNLIKELY(expr) (expr) |
| #endif |
| |
| // ---------------- Static Inline Functions |
| // |
| // The helpers below are functions, instead of macros, because their arguments |
| // can be an expression that we shouldn't evaluate more than once. |
| // |
| // They are in base-impl.h and hence copy/pasted into every generated C file, |
| // instead of being in some "base.c" file, since a design goal is that users of |
| // the generated C code can often just #include a single .c file, such as |
| // "gif.c", without having to additionally include or otherwise build and link |
| // a "base.c" file. |
| // |
| // They are static, so that linking multiple puffs .o files won't complain about |
| // duplicate function definitions. |
| // |
| // They are explicitly marked inline, even if modern compilers don't use the |
| // inline attribute to guide optimizations such as inlining, to avoid the |
| // -Wunused-function warning, and we like to compile with -Wall -Werror. |
| |
| static inline uint16_t puffs_base__load_u16be(uint8_t* p) { |
| return ((uint16_t)(p[0]) << 8) | ((uint16_t)(p[1]) << 0); |
| } |
| |
| static inline uint16_t puffs_base__load_u16le(uint8_t* p) { |
| return ((uint16_t)(p[0]) << 0) | ((uint16_t)(p[1]) << 8); |
| } |
| |
| static inline uint32_t puffs_base__load_u32be(uint8_t* p) { |
| return ((uint32_t)(p[0]) << 24) | ((uint32_t)(p[1]) << 16) | |
| ((uint32_t)(p[2]) << 8) | ((uint32_t)(p[3]) << 0); |
| } |
| |
| static inline uint32_t puffs_base__load_u32le(uint8_t* p) { |
| return ((uint32_t)(p[0]) << 0) | ((uint32_t)(p[1]) << 8) | |
| ((uint32_t)(p[2]) << 16) | ((uint32_t)(p[3]) << 24); |
| } |
| |
| static inline puffs_base__slice_u8 puffs_base__slice_u8__subslice_i( |
| puffs_base__slice_u8 s, |
| uint64_t i) { |
| if ((i <= SIZE_MAX) && (i <= s.len)) { |
| return ((puffs_base__slice_u8){ |
| .ptr = s.ptr + i, |
| .len = s.len - i, |
| }); |
| } |
| return ((puffs_base__slice_u8){}); |
| } |
| |
| static inline puffs_base__slice_u8 puffs_base__slice_u8__subslice_j( |
| puffs_base__slice_u8 s, |
| uint64_t j) { |
| if ((j <= SIZE_MAX) && (j <= s.len)) { |
| return ((puffs_base__slice_u8){.ptr = s.ptr, .len = j}); |
| } |
| return ((puffs_base__slice_u8){}); |
| } |
| |
| static inline puffs_base__slice_u8 puffs_base__slice_u8__subslice_ij( |
| puffs_base__slice_u8 s, |
| uint64_t i, |
| uint64_t j) { |
| if ((i <= j) && (j <= SIZE_MAX) && (j <= s.len)) { |
| return ((puffs_base__slice_u8){ |
| .ptr = s.ptr + i, |
| .len = j - i, |
| }); |
| } |
| return ((puffs_base__slice_u8){}); |
| } |
| |
| // puffs_base__slice_u8__prefix returns up to the first up_to bytes of s. |
| static inline puffs_base__slice_u8 puffs_base__slice_u8__prefix( |
| puffs_base__slice_u8 s, |
| uint64_t up_to) { |
| if ((uint64_t)(s.len) > up_to) { |
| s.len = up_to; |
| } |
| return s; |
| } |
| |
| // puffs_base__slice_u8__suffix returns up to the last up_to bytes of s. |
| static inline puffs_base__slice_u8 puffs_base__slice_u8_suffix( |
| puffs_base__slice_u8 s, |
| uint64_t up_to) { |
| if ((uint64_t)(s.len) > up_to) { |
| s.ptr += (uint64_t)(s.len) - up_to; |
| s.len = up_to; |
| } |
| return s; |
| } |
| |
| // puffs_base__slice_u8__copy_from_slice calls memmove(dst.ptr, src.ptr, |
| // length) where length is the minimum of dst.len and src.len. |
| // |
| // Passing a puffs_base__slice_u8 with all fields NULL or zero (a valid, empty |
| // slice) is valid and results in a no-op. |
| static inline uint64_t puffs_base__slice_u8__copy_from_slice( |
| puffs_base__slice_u8 dst, |
| puffs_base__slice_u8 src) { |
| size_t length = dst.len < src.len ? dst.len : src.len; |
| if (length > 0) { |
| memmove(dst.ptr, src.ptr, length); |
| } |
| return length; |
| } |
| |
| static inline uint32_t puffs_base__writer1__copy_from_history32( |
| uint8_t** ptr_ptr, |
| uint8_t* start, |
| uint8_t* end, |
| uint32_t distance, |
| uint32_t length) { |
| uint8_t* ptr = *ptr_ptr; |
| size_t d = ptr - start; |
| if ((d == 0) || (d < (size_t)(distance))) { |
| return 0; |
| } |
| start = ptr - distance; |
| size_t n = end - ptr; |
| if ((size_t)(length) > n) { |
| length = n; |
| } else { |
| n = length; |
| } |
| // TODO: is manual unrolling actually helpful? |
| for (; n >= 8; n -= 8) { |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| *ptr++ = *start++; |
| } |
| for (; n; n--) { |
| *ptr++ = *start++; |
| } |
| *ptr_ptr = ptr; |
| return length; |
| } |
| |
| static inline uint32_t puffs_base__writer1__copy_from_reader32( |
| uint8_t** ptr_wptr, |
| uint8_t* wend, |
| uint8_t** ptr_rptr, |
| uint8_t* rend, |
| uint32_t length) { |
| uint8_t* wptr = *ptr_wptr; |
| size_t n = length; |
| if (n > wend - wptr) { |
| n = wend - wptr; |
| } |
| uint8_t* rptr = *ptr_rptr; |
| if (n > rend - rptr) { |
| n = rend - rptr; |
| } |
| if (n > 0) { |
| memmove(wptr, rptr, n); |
| *ptr_wptr += n; |
| *ptr_rptr += n; |
| } |
| return n; |
| } |
| |
| static inline uint64_t puffs_base__writer1__copy_from_slice( |
| uint8_t** ptr_wptr, |
| uint8_t* wend, |
| puffs_base__slice_u8 src) { |
| uint8_t* wptr = *ptr_wptr; |
| size_t n = src.len; |
| if (n > wend - wptr) { |
| n = wend - wptr; |
| } |
| if (n > 0) { |
| memmove(wptr, src.ptr, n); |
| *ptr_wptr += n; |
| } |
| return n; |
| } |
| |
| static inline uint32_t puffs_base__writer1__copy_from_slice32( |
| uint8_t** ptr_wptr, |
| uint8_t* wend, |
| puffs_base__slice_u8 src, |
| uint32_t length) { |
| uint8_t* wptr = *ptr_wptr; |
| size_t n = src.len; |
| if (n > length) { |
| n = length; |
| } |
| if (n > wend - wptr) { |
| n = wend - wptr; |
| } |
| if (n > 0) { |
| memmove(wptr, src.ptr, n); |
| *ptr_wptr += n; |
| } |
| return n; |
| } |
| |
| #endif // PUFFS_BASE_IMPL_H |
| |
| // ---------------- Status Codes Implementations |
| |
| bool puffs_flate__status__is_error(puffs_flate__status s) { |
| return s < 0; |
| } |
| |
| const char* puffs_flate__status__strings0[9] = { |
| "flate: ok", |
| "flate: bad puffs version", |
| "flate: bad receiver", |
| "flate: bad argument", |
| "flate: initializer not called", |
| "flate: closed for writes", |
| "flate: unexpected EOF", |
| "flate: short read", |
| "flate: short write", |
| }; |
| |
| const char* puffs_flate__status__strings1[20] = { |
| "flate: bad Huffman code (over-subscribed)", |
| "flate: bad Huffman code (under-subscribed)", |
| "flate: bad Huffman code length count", |
| "flate: bad Huffman code length repetition", |
| "flate: bad Huffman code", |
| "flate: bad Huffman minimum code length", |
| "flate: bad distance", |
| "flate: bad distance code count", |
| "flate: bad flate block", |
| "flate: bad literal/length code count", |
| "flate: checksum mismatch", |
| "flate: inconsistent stored block length", |
| "flate: internal error: inconsistent Huffman decoder state", |
| "flate: internal error: inconsistent n_bits", |
| "flate: missing end-of-block code", |
| "flate: no Huffman codes", |
| "flate: invalid zlib compression method", |
| "flate: invalid zlib compression window size", |
| "flate: invalid zlib parity check", |
| "flate: TODO: unsupported zlib preset dictionary", |
| }; |
| |
| const char* puffs_flate__status__string(puffs_flate__status s) { |
| const char** a = NULL; |
| uint32_t n = 0; |
| switch ((s >> 10) & 0x1fffff) { |
| case 0: |
| a = puffs_flate__status__strings0; |
| n = 9; |
| break; |
| case puffs_flate__packageid: |
| a = puffs_flate__status__strings1; |
| n = 20; |
| break; |
| } |
| uint32_t i = s & 0xff; |
| return i < n ? a[i] : "flate: unknown status"; |
| } |
| |
| // ---------------- Private Consts |
| |
| static const uint8_t puffs_flate__code_order[19] = { |
| 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, |
| }; |
| |
| static const uint8_t puffs_flate__reverse8[256] = { |
| 0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240, |
| 8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248, |
| 4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244, |
| 12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252, |
| 2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242, |
| 10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250, |
| 6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246, |
| 14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254, |
| 1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241, |
| 9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249, |
| 5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245, |
| 13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253, |
| 3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243, |
| 11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251, |
| 7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247, |
| 15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255, |
| }; |
| |
| static const uint32_t puffs_flate__lcode_magic_numbers[32] = { |
| 1073742592, 1073742848, 1073743104, 1073743360, 1073743616, 1073743872, |
| 1073744128, 1073744384, 1073744656, 1073745168, 1073745680, 1073746192, |
| 1073746720, 1073747744, 1073748768, 1073749792, 1073750832, 1073752880, |
| 1073754928, 1073756976, 1073759040, 1073763136, 1073767232, 1073771328, |
| 1073775440, 1073783632, 1073791824, 1073800016, 1073807872, 134217728, |
| 134217728, 134217728, |
| }; |
| |
| static const uint32_t puffs_flate__dcode_magic_numbers[32] = { |
| 1073742080, 1073742336, 1073742592, 1073742848, 1073743120, 1073743632, |
| 1073744160, 1073745184, 1073746224, 1073748272, 1073750336, 1073754432, |
| 1073758544, 1073766736, 1073774944, 1073791328, 1073807728, 1073840496, |
| 1073873280, 1073938816, 1074004368, 1074135440, 1074266528, 1074528672, |
| 1074790832, 1075315120, 1075839424, 1076888000, 1077936592, 1080033744, |
| 134217728, 134217728, |
| }; |
| |
| // ---------------- Private Initializer Prototypes |
| |
| void puffs_flate__adler32__initialize(puffs_flate__adler32* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only); |
| |
| // ---------------- Private Function Prototypes |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_blocks( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src); |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_uncompressed( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src); |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_huffman( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src); |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_fixed_huffman( |
| puffs_flate__flate_decoder* self); |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_dynamic_huffman( |
| puffs_flate__flate_decoder* self, |
| puffs_base__reader1 a_src); |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_huff( |
| puffs_flate__flate_decoder* self, |
| uint32_t a_which, |
| uint32_t a_n_codes0, |
| uint32_t a_n_codes1, |
| uint32_t a_base_symbol); |
| |
| uint32_t puffs_flate__adler32__update(puffs_flate__adler32* self, |
| puffs_base__slice_u8 a_x); |
| |
| // ---------------- Initializer Implementations |
| |
| void puffs_flate__flate_decoder__initialize(puffs_flate__flate_decoder* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only) { |
| if (!self) { |
| return; |
| } |
| if (puffs_version != PUFFS_VERSION) { |
| self->private_impl.status = PUFFS_FLATE__ERROR_BAD_PUFFS_VERSION; |
| return; |
| } |
| if (for_internal_use_only != PUFFS_BASE__ALREADY_ZEROED) { |
| memset(self, 0, sizeof(*self)); |
| } |
| self->private_impl.magic = PUFFS_BASE__MAGIC; |
| } |
| |
| void puffs_flate__adler32__initialize(puffs_flate__adler32* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only) { |
| if (!self) { |
| return; |
| } |
| if (puffs_version != PUFFS_VERSION) { |
| self->private_impl.status = PUFFS_FLATE__ERROR_BAD_PUFFS_VERSION; |
| return; |
| } |
| if (for_internal_use_only != PUFFS_BASE__ALREADY_ZEROED) { |
| memset(self, 0, sizeof(*self)); |
| } |
| self->private_impl.magic = PUFFS_BASE__MAGIC; |
| self->private_impl.f_state = 1; |
| } |
| |
| void puffs_flate__zlib_decoder__initialize(puffs_flate__zlib_decoder* self, |
| uint32_t puffs_version, |
| uint32_t for_internal_use_only) { |
| if (!self) { |
| return; |
| } |
| if (puffs_version != PUFFS_VERSION) { |
| self->private_impl.status = PUFFS_FLATE__ERROR_BAD_PUFFS_VERSION; |
| return; |
| } |
| if (for_internal_use_only != PUFFS_BASE__ALREADY_ZEROED) { |
| memset(self, 0, sizeof(*self)); |
| } |
| self->private_impl.magic = PUFFS_BASE__MAGIC; |
| puffs_flate__flate_decoder__initialize( |
| &self->private_impl.f_flate, PUFFS_VERSION, PUFFS_BASE__ALREADY_ZEROED); |
| puffs_flate__adler32__initialize(&self->private_impl.f_adler, PUFFS_VERSION, |
| PUFFS_BASE__ALREADY_ZEROED); |
| } |
| |
| // ---------------- Function Implementations |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src) { |
| if (!self) { |
| return PUFFS_FLATE__ERROR_BAD_RECEIVER; |
| } |
| if (self->private_impl.magic != PUFFS_BASE__MAGIC) { |
| self->private_impl.status = PUFFS_FLATE__ERROR_INITIALIZER_NOT_CALLED; |
| } |
| if (self->private_impl.status < 0) { |
| return self->private_impl.status; |
| } |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| puffs_flate__status v_z; |
| puffs_base__slice_u8 v_written; |
| uint64_t v_n_copied; |
| uint32_t v_already_full; |
| |
| uint8_t* b_wptr_dst = NULL; |
| uint8_t* b_wstart_dst = NULL; |
| uint8_t* b_wend_dst = NULL; |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wstart_dst = b_wptr_dst; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| |
| uint32_t coro_susp_point = self->private_impl.c_decode[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_z = self->private_impl.c_decode[0].v_z; |
| v_written = ((puffs_base__slice_u8){}); |
| v_n_copied = self->private_impl.c_decode[0].v_n_copied; |
| v_already_full = self->private_impl.c_decode[0].v_already_full; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| /* placeholder */ |
| while (true) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| puffs_flate__status t_0 = |
| puffs_flate__flate_decoder__decode_blocks(self, a_dst, a_src); |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| v_z = t_0; |
| if (!(v_z > 0)) { |
| status = v_z; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(2); |
| } |
| v_written = ((puffs_base__slice_u8){ |
| .ptr = b_wstart_dst, |
| .len = b_wptr_dst - b_wstart_dst, |
| }); |
| if (((uint64_t)(v_written.len)) >= 32768) { |
| v_written = puffs_base__slice_u8_suffix(v_written, 32768); |
| puffs_base__slice_u8__copy_from_slice( |
| ((puffs_base__slice_u8){.ptr = self->private_impl.f_history, |
| .len = 32768}), |
| v_written); |
| self->private_impl.f_history_index = 32768; |
| } else { |
| v_n_copied = puffs_base__slice_u8__copy_from_slice( |
| puffs_base__slice_u8__subslice_i( |
| ((puffs_base__slice_u8){.ptr = self->private_impl.f_history, |
| .len = 32768}), |
| self->private_impl.f_history_index & 32767), |
| v_written); |
| if (v_n_copied < ((uint64_t)(v_written.len))) { |
| v_written = puffs_base__slice_u8__subslice_i(v_written, v_n_copied); |
| v_n_copied = puffs_base__slice_u8__copy_from_slice( |
| ((puffs_base__slice_u8){.ptr = self->private_impl.f_history, |
| .len = 32768}), |
| v_written); |
| self->private_impl.f_history_index = |
| (((uint32_t)((v_n_copied & 32767))) + 32768); |
| } else { |
| v_already_full = 0; |
| if (self->private_impl.f_history_index >= 32768) { |
| v_already_full = 32768; |
| } |
| self->private_impl.f_history_index = |
| ((self->private_impl.f_history_index & 32767) + |
| ((uint32_t)((v_n_copied & 32767))) + v_already_full); |
| } |
| } |
| status = v_z; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); |
| } |
| |
| goto ok; |
| ok: |
| self->private_impl.c_decode[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_decode[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_decode[0].v_z = v_z; |
| self->private_impl.c_decode[0].v_n_copied = v_n_copied; |
| self->private_impl.c_decode[0].v_already_full = v_already_full; |
| |
| exit: |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wstart_dst); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wend_dst); |
| } |
| |
| self->private_impl.status = status; |
| return status; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_blocks( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint32_t v_final; |
| uint32_t v_type; |
| |
| uint8_t* b_rptr_src = NULL; |
| uint8_t* b_rstart_src = NULL; |
| uint8_t* b_rend_src = NULL; |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| b_rstart_src = b_rptr_src; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| |
| uint32_t coro_susp_point = |
| self->private_impl.c_decode_blocks[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_final = self->private_impl.c_decode_blocks[0].v_final; |
| v_type = self->private_impl.c_decode_blocks[0].v_type; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| v_final = 0; |
| label_0_continue:; |
| while (v_final == 0) { |
| while (self->private_impl.f_n_bits < 3) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_0 = *b_rptr_src++; |
| self->private_impl.f_bits |= |
| (((uint32_t)(t_0)) << self->private_impl.f_n_bits); |
| self->private_impl.f_n_bits += 8; |
| } |
| v_final = (self->private_impl.f_bits & 1); |
| v_type = ((self->private_impl.f_bits >> 1) & 3); |
| self->private_impl.f_bits >>= 3; |
| self->private_impl.f_n_bits -= 3; |
| if (v_type == 0) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| status = |
| puffs_flate__flate_decoder__decode_uncompressed(self, a_dst, a_src); |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| if (status) { |
| goto suspend; |
| } |
| goto label_0_continue; |
| } else if (v_type == 1) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); |
| status = puffs_flate__flate_decoder__init_fixed_huffman(self); |
| if (status) { |
| goto suspend; |
| } |
| } else if (v_type == 2) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| status = puffs_flate__flate_decoder__init_dynamic_huffman(self, a_src); |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| if (status) { |
| goto suspend; |
| } |
| } else { |
| status = PUFFS_FLATE__ERROR_BAD_FLATE_BLOCK; |
| goto exit; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| status = puffs_flate__flate_decoder__decode_huffman(self, a_dst, a_src); |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| if (status) { |
| goto suspend; |
| } |
| } |
| |
| goto ok; |
| ok: |
| self->private_impl.c_decode_blocks[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_decode_blocks[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_decode_blocks[0].v_final = v_final; |
| self->private_impl.c_decode_blocks[0].v_type = v_type; |
| |
| exit: |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rstart_src); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rend_src); |
| } |
| |
| return status; |
| |
| short_read_src: |
| if (a_src.buf && a_src.buf->closed && !a_src.limit.ptr_to_len) { |
| status = PUFFS_FLATE__ERROR_UNEXPECTED_EOF; |
| goto exit; |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| goto suspend; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_uncompressed( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint32_t v_length; |
| uint32_t v_n_copied; |
| |
| uint8_t* b_wptr_dst = NULL; |
| uint8_t* b_wstart_dst = NULL; |
| uint8_t* b_wend_dst = NULL; |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wstart_dst = b_wptr_dst; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| uint8_t* b_rptr_src = NULL; |
| uint8_t* b_rstart_src = NULL; |
| uint8_t* b_rend_src = NULL; |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| b_rstart_src = b_rptr_src; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| |
| uint32_t coro_susp_point = |
| self->private_impl.c_decode_uncompressed[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_length = self->private_impl.c_decode_uncompressed[0].v_length; |
| v_n_copied = self->private_impl.c_decode_uncompressed[0].v_n_copied; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| if (self->private_impl.f_n_bits >= 8) { |
| status = PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_N_BITS; |
| goto exit; |
| } |
| self->private_impl.f_n_bits = 0; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| uint32_t t_1; |
| if (PUFFS_BASE__LIKELY(b_rend_src - b_rptr_src >= 4)) { |
| t_1 = puffs_base__load_u32le(b_rptr_src); |
| b_rptr_src += 4; |
| } else { |
| self->private_impl.c_decode_uncompressed[0].scratch = 0; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| while (true) { |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint32_t t_0 = |
| self->private_impl.c_decode_uncompressed[0].scratch >> 56; |
| self->private_impl.c_decode_uncompressed[0].scratch <<= 8; |
| self->private_impl.c_decode_uncompressed[0].scratch >>= 8; |
| self->private_impl.c_decode_uncompressed[0].scratch |= |
| ((uint64_t)(*b_rptr_src++)) << t_0; |
| if (t_0 == 24) { |
| t_1 = self->private_impl.c_decode_uncompressed[0].scratch; |
| break; |
| } |
| t_0 += 8; |
| self->private_impl.c_decode_uncompressed[0].scratch |= ((uint64_t)(t_0)) |
| << 56; |
| } |
| } |
| v_length = t_1; |
| if ((((v_length) & ((1 << (16)) - 1)) + ((v_length) >> (32 - (16)))) != |
| 65535) { |
| status = PUFFS_FLATE__ERROR_INCONSISTENT_STORED_BLOCK_LENGTH; |
| goto exit; |
| } |
| v_length = ((v_length) & ((1 << (16)) - 1)); |
| while (true) { |
| v_n_copied = puffs_base__writer1__copy_from_reader32( |
| &b_wptr_dst, b_wend_dst, &b_rptr_src, b_rend_src, v_length); |
| if (v_length <= v_n_copied) { |
| v_length = 0; |
| goto label_0_break; |
| } |
| v_length -= v_n_copied; |
| if (((uint64_t)(b_wend_dst - b_wptr_dst)) == 0) { |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(3); |
| } else { |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); |
| } |
| } |
| label_0_break:; |
| |
| goto ok; |
| ok: |
| self->private_impl.c_decode_uncompressed[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_decode_uncompressed[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_decode_uncompressed[0].v_length = v_length; |
| self->private_impl.c_decode_uncompressed[0].v_n_copied = v_n_copied; |
| |
| exit: |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wstart_dst); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wend_dst); |
| } |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rstart_src); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rend_src); |
| } |
| |
| return status; |
| |
| short_read_src: |
| if (a_src.buf && a_src.buf->closed && !a_src.limit.ptr_to_len) { |
| status = PUFFS_FLATE__ERROR_UNEXPECTED_EOF; |
| goto exit; |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| goto suspend; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__decode_huffman( |
| puffs_flate__flate_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint32_t v_bits; |
| uint32_t v_n_bits; |
| uint32_t v_table_entry; |
| uint32_t v_table_entry_n_bits; |
| uint32_t v_lmask; |
| uint32_t v_dmask; |
| uint32_t v_redir_top; |
| uint32_t v_redir_mask; |
| uint32_t v_length; |
| uint32_t v_distance; |
| uint32_t v_n_copied; |
| uint32_t v_hlen; |
| uint32_t v_hdist; |
| |
| uint8_t* b_wptr_dst = NULL; |
| uint8_t* b_wstart_dst = NULL; |
| uint8_t* b_wend_dst = NULL; |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wstart_dst = b_wptr_dst; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| uint8_t* b_rptr_src = NULL; |
| uint8_t* b_rstart_src = NULL; |
| uint8_t* b_rend_src = NULL; |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| b_rstart_src = b_rptr_src; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| |
| uint32_t coro_susp_point = |
| self->private_impl.c_decode_huffman[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_bits = self->private_impl.c_decode_huffman[0].v_bits; |
| v_n_bits = self->private_impl.c_decode_huffman[0].v_n_bits; |
| v_table_entry = self->private_impl.c_decode_huffman[0].v_table_entry; |
| v_table_entry_n_bits = |
| self->private_impl.c_decode_huffman[0].v_table_entry_n_bits; |
| v_lmask = self->private_impl.c_decode_huffman[0].v_lmask; |
| v_dmask = self->private_impl.c_decode_huffman[0].v_dmask; |
| v_redir_top = self->private_impl.c_decode_huffman[0].v_redir_top; |
| v_redir_mask = self->private_impl.c_decode_huffman[0].v_redir_mask; |
| v_length = self->private_impl.c_decode_huffman[0].v_length; |
| v_distance = self->private_impl.c_decode_huffman[0].v_distance; |
| v_n_copied = self->private_impl.c_decode_huffman[0].v_n_copied; |
| v_hlen = self->private_impl.c_decode_huffman[0].v_hlen; |
| v_hdist = self->private_impl.c_decode_huffman[0].v_hdist; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| v_bits = self->private_impl.f_bits; |
| v_n_bits = self->private_impl.f_n_bits; |
| v_table_entry = 0; |
| v_table_entry_n_bits = 0; |
| v_lmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1); |
| v_dmask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[1]) - 1); |
| label_0_continue:; |
| while (true) { |
| while (true) { |
| v_table_entry = self->private_impl.f_huffs[0][v_bits & v_lmask]; |
| v_table_entry_n_bits = (v_table_entry & 15); |
| if (v_n_bits >= v_table_entry_n_bits) { |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| goto label_1_break; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_0 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_0)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| label_1_break:; |
| if ((v_table_entry >> 31) != 0) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| if (b_wptr_dst == b_wend_dst) { |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| goto suspend; |
| } |
| *b_wptr_dst++ = ((v_table_entry >> 8) & 255); |
| goto label_0_continue; |
| } else if ((v_table_entry >> 30) != 0) { |
| } else if ((v_table_entry >> 29) != 0) { |
| goto label_0_break; |
| } else if ((v_table_entry >> 28) != 0) { |
| v_redir_top = ((v_table_entry >> 8) & 65535); |
| v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1); |
| while (true) { |
| if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_table_entry = |
| self->private_impl |
| .f_huffs[0][v_redir_top + (v_bits & v_redir_mask)]; |
| v_table_entry_n_bits = (v_table_entry & 15); |
| if (v_n_bits >= v_table_entry_n_bits) { |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| goto label_2_break; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_1 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_1)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| label_2_break:; |
| if ((v_table_entry >> 31) != 0) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); |
| if (b_wptr_dst == b_wend_dst) { |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| goto suspend; |
| } |
| *b_wptr_dst++ = ((v_table_entry >> 8) & 255); |
| goto label_0_continue; |
| } else if ((v_table_entry >> 30) != 0) { |
| } else if ((v_table_entry >> 29) != 0) { |
| goto label_0_break; |
| } else if ((v_table_entry >> 28) != 0) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } else if ((v_table_entry >> 27) != 0) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE; |
| goto exit; |
| } else { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| } else if ((v_table_entry >> 27) != 0) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE; |
| goto exit; |
| } else { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_length = ((v_table_entry >> 8) & 32767); |
| v_table_entry_n_bits = ((v_table_entry >> 4) & 15); |
| while (v_n_bits < v_table_entry_n_bits) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_2 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_2)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| v_length = |
| ((v_length + ((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) & |
| 32767); |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| while (true) { |
| v_table_entry = self->private_impl.f_huffs[1][v_bits & v_dmask]; |
| v_table_entry_n_bits = (v_table_entry & 15); |
| if (v_n_bits >= v_table_entry_n_bits) { |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| goto label_3_break; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_3 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_3)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| label_3_break:; |
| if ((v_table_entry >> 28) == 1) { |
| v_redir_top = ((v_table_entry >> 8) & 65535); |
| v_redir_mask = ((((uint32_t)(1)) << ((v_table_entry >> 4) & 15)) - 1); |
| while (true) { |
| if ((v_redir_top + (v_bits & v_redir_mask)) >= 1234) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_table_entry = |
| self->private_impl |
| .f_huffs[1][v_redir_top + (v_bits & v_redir_mask)]; |
| v_table_entry_n_bits = (v_table_entry & 15); |
| if (v_n_bits >= v_table_entry_n_bits) { |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| goto label_4_break; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_4 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_4)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| label_4_break:; |
| if ((v_table_entry >> 31) != 0) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| } |
| if ((v_table_entry >> 24) != 64) { |
| if ((v_table_entry >> 24) == 8) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE; |
| goto exit; |
| } |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_distance = ((v_table_entry >> 8) & 32767); |
| v_table_entry_n_bits = ((v_table_entry >> 4) & 15); |
| while (v_n_bits < v_table_entry_n_bits) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(8); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_5 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_5)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| v_distance = |
| ((v_distance + ((v_bits) & ((1 << (v_table_entry_n_bits)) - 1))) & |
| 32767); |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| v_n_copied = 0; |
| while (true) { |
| if (((uint64_t)(v_distance)) > |
| ((uint64_t)(b_wptr_dst - b_wstart_dst))) { |
| v_hlen = 0; |
| v_hdist = ((uint32_t)((((uint64_t)(v_distance)) - |
| ((uint64_t)(b_wptr_dst - b_wstart_dst))))); |
| if (v_length > v_hdist) { |
| v_length -= v_hdist; |
| v_hlen = v_hdist; |
| } else { |
| v_hlen = v_length; |
| v_length = 0; |
| } |
| if (self->private_impl.f_history_index < v_hdist) { |
| status = PUFFS_FLATE__ERROR_BAD_DISTANCE; |
| goto exit; |
| } |
| v_hdist = ((self->private_impl.f_history_index - v_hdist) & 32767); |
| while (true) { |
| v_n_copied = puffs_base__writer1__copy_from_slice32( |
| &b_wptr_dst, b_wend_dst, |
| puffs_base__slice_u8__subslice_i( |
| ((puffs_base__slice_u8){.ptr = self->private_impl.f_history, |
| .len = 32768}), |
| v_hdist), |
| v_hlen); |
| if (v_hlen <= v_n_copied) { |
| v_hlen = 0; |
| goto label_5_break; |
| } |
| if (v_n_copied > 0) { |
| v_hlen -= v_n_copied; |
| v_hdist = ((v_hdist + v_n_copied) & 32767); |
| if (v_hdist == 0) { |
| goto label_5_break; |
| } |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(9); |
| } |
| label_5_break:; |
| if (v_hlen > 0) { |
| while (true) { |
| v_n_copied = puffs_base__writer1__copy_from_slice32( |
| &b_wptr_dst, b_wend_dst, |
| puffs_base__slice_u8__subslice_i( |
| ((puffs_base__slice_u8){ |
| .ptr = self->private_impl.f_history, .len = 32768}), |
| v_hdist), |
| v_hlen); |
| if (v_hlen <= v_n_copied) { |
| v_hlen = 0; |
| goto label_6_break; |
| } |
| v_hlen -= v_n_copied; |
| v_hdist = ((v_hdist + (v_n_copied & 32767)) & 32767); |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(10); |
| } |
| label_6_break:; |
| } |
| if (v_length == 0) { |
| goto label_0_continue; |
| } |
| } |
| v_n_copied = puffs_base__writer1__copy_from_history32( |
| &b_wptr_dst, b_wstart_dst, b_wend_dst, v_distance, v_length); |
| if (v_length <= v_n_copied) { |
| v_length = 0; |
| goto label_7_break; |
| } |
| v_length -= v_n_copied; |
| status = PUFFS_FLATE__SUSPENSION_SHORT_WRITE; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(11); |
| } |
| label_7_break:; |
| } |
| label_0_break:; |
| self->private_impl.f_bits = v_bits; |
| self->private_impl.f_n_bits = v_n_bits; |
| |
| goto ok; |
| ok: |
| self->private_impl.c_decode_huffman[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_decode_huffman[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_decode_huffman[0].v_bits = v_bits; |
| self->private_impl.c_decode_huffman[0].v_n_bits = v_n_bits; |
| self->private_impl.c_decode_huffman[0].v_table_entry = v_table_entry; |
| self->private_impl.c_decode_huffman[0].v_table_entry_n_bits = |
| v_table_entry_n_bits; |
| self->private_impl.c_decode_huffman[0].v_lmask = v_lmask; |
| self->private_impl.c_decode_huffman[0].v_dmask = v_dmask; |
| self->private_impl.c_decode_huffman[0].v_redir_top = v_redir_top; |
| self->private_impl.c_decode_huffman[0].v_redir_mask = v_redir_mask; |
| self->private_impl.c_decode_huffman[0].v_length = v_length; |
| self->private_impl.c_decode_huffman[0].v_distance = v_distance; |
| self->private_impl.c_decode_huffman[0].v_n_copied = v_n_copied; |
| self->private_impl.c_decode_huffman[0].v_hlen = v_hlen; |
| self->private_impl.c_decode_huffman[0].v_hdist = v_hdist; |
| |
| exit: |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wstart_dst); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wend_dst); |
| } |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rstart_src); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rend_src); |
| } |
| |
| return status; |
| |
| short_read_src: |
| if (a_src.buf && a_src.buf->closed && !a_src.limit.ptr_to_len) { |
| status = PUFFS_FLATE__ERROR_UNEXPECTED_EOF; |
| goto exit; |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| goto suspend; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_fixed_huffman( |
| puffs_flate__flate_decoder* self) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint32_t v_i; |
| |
| uint32_t coro_susp_point = |
| self->private_impl.c_init_fixed_huffman[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_i = self->private_impl.c_init_fixed_huffman[0].v_i; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| v_i = 0; |
| while (v_i < 144) { |
| self->private_impl.f_code_lengths[v_i] = 8; |
| v_i += 1; |
| } |
| while (v_i < 256) { |
| self->private_impl.f_code_lengths[v_i] = 9; |
| v_i += 1; |
| } |
| while (v_i < 280) { |
| self->private_impl.f_code_lengths[v_i] = 7; |
| v_i += 1; |
| } |
| while (v_i < 288) { |
| self->private_impl.f_code_lengths[v_i] = 8; |
| v_i += 1; |
| } |
| while (v_i < 320) { |
| self->private_impl.f_code_lengths[v_i] = 5; |
| v_i += 1; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| status = puffs_flate__flate_decoder__init_huff(self, 0, 0, 288, 257); |
| if (status) { |
| goto suspend; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| status = puffs_flate__flate_decoder__init_huff(self, 1, 288, 320, 0); |
| if (status) { |
| goto suspend; |
| } |
| |
| goto ok; |
| ok: |
| self->private_impl.c_init_fixed_huffman[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_init_fixed_huffman[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_init_fixed_huffman[0].v_i = v_i; |
| |
| exit: |
| return status; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_dynamic_huffman( |
| puffs_flate__flate_decoder* self, |
| puffs_base__reader1 a_src) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint32_t v_bits; |
| uint32_t v_n_bits; |
| uint32_t v_n_lit; |
| uint32_t v_n_dist; |
| uint32_t v_n_clen; |
| uint32_t v_i; |
| uint32_t v_mask; |
| uint32_t v_table_entry; |
| uint32_t v_table_entry_n_bits; |
| uint32_t v_n_extra_bits; |
| uint8_t v_rep_symbol; |
| uint32_t v_rep_count; |
| |
| uint8_t* b_rptr_src = NULL; |
| uint8_t* b_rstart_src = NULL; |
| uint8_t* b_rend_src = NULL; |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| b_rstart_src = b_rptr_src; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| |
| uint32_t coro_susp_point = |
| self->private_impl.c_init_dynamic_huffman[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_bits = self->private_impl.c_init_dynamic_huffman[0].v_bits; |
| v_n_bits = self->private_impl.c_init_dynamic_huffman[0].v_n_bits; |
| v_n_lit = self->private_impl.c_init_dynamic_huffman[0].v_n_lit; |
| v_n_dist = self->private_impl.c_init_dynamic_huffman[0].v_n_dist; |
| v_n_clen = self->private_impl.c_init_dynamic_huffman[0].v_n_clen; |
| v_i = self->private_impl.c_init_dynamic_huffman[0].v_i; |
| v_mask = self->private_impl.c_init_dynamic_huffman[0].v_mask; |
| v_table_entry = self->private_impl.c_init_dynamic_huffman[0].v_table_entry; |
| v_table_entry_n_bits = |
| self->private_impl.c_init_dynamic_huffman[0].v_table_entry_n_bits; |
| v_n_extra_bits = |
| self->private_impl.c_init_dynamic_huffman[0].v_n_extra_bits; |
| v_rep_symbol = self->private_impl.c_init_dynamic_huffman[0].v_rep_symbol; |
| v_rep_count = self->private_impl.c_init_dynamic_huffman[0].v_rep_count; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| v_bits = self->private_impl.f_bits; |
| v_n_bits = self->private_impl.f_n_bits; |
| while (v_n_bits < 14) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_0 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_0)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| v_n_lit = (((v_bits) & ((1 << (5)) - 1)) + 257); |
| if (v_n_lit > 286) { |
| status = PUFFS_FLATE__ERROR_BAD_LITERAL_LENGTH_CODE_COUNT; |
| goto exit; |
| } |
| v_bits >>= 5; |
| v_n_dist = (((v_bits) & ((1 << (5)) - 1)) + 1); |
| if (v_n_dist > 30) { |
| status = PUFFS_FLATE__ERROR_BAD_DISTANCE_CODE_COUNT; |
| goto exit; |
| } |
| v_bits >>= 5; |
| v_n_clen = (((v_bits) & ((1 << (4)) - 1)) + 4); |
| v_bits >>= 4; |
| v_n_bits -= 14; |
| v_i = 0; |
| while (v_i < v_n_clen) { |
| while (v_n_bits < 3) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_1 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_1)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| self->private_impl.f_code_lengths[puffs_flate__code_order[v_i]] = |
| ((uint8_t)((v_bits & 7))); |
| v_bits >>= 3; |
| v_n_bits -= 3; |
| v_i += 1; |
| } |
| while (v_i < 19) { |
| self->private_impl.f_code_lengths[puffs_flate__code_order[v_i]] = 0; |
| v_i += 1; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); |
| status = puffs_flate__flate_decoder__init_huff(self, 0, 0, 19, 4095); |
| if (status) { |
| goto suspend; |
| } |
| v_mask = ((((uint32_t)(1)) << self->private_impl.f_n_huffs_bits[0]) - 1); |
| v_i = 0; |
| label_0_continue:; |
| while (v_i < (v_n_lit + v_n_dist)) { |
| v_table_entry = 0; |
| while (true) { |
| v_table_entry = self->private_impl.f_huffs[0][v_bits & v_mask]; |
| v_table_entry_n_bits = (v_table_entry & 15); |
| if (v_n_bits >= v_table_entry_n_bits) { |
| v_bits >>= v_table_entry_n_bits; |
| v_n_bits -= v_table_entry_n_bits; |
| goto label_1_break; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(4); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_2 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_2)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| label_1_break:; |
| if ((v_table_entry >> 24) != 128) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_table_entry = ((v_table_entry >> 8) & 255); |
| if (v_table_entry < 16) { |
| self->private_impl.f_code_lengths[v_i] = ((uint8_t)(v_table_entry)); |
| v_i += 1; |
| goto label_0_continue; |
| } |
| v_n_extra_bits = 0; |
| v_rep_symbol = 0; |
| v_rep_count = 0; |
| if (v_table_entry == 16) { |
| v_n_extra_bits = 2; |
| if (v_i <= 0) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_REPETITION; |
| goto exit; |
| } |
| v_rep_symbol = self->private_impl.f_code_lengths[v_i - 1]; |
| v_rep_count = 3; |
| } else if (v_table_entry == 17) { |
| v_n_extra_bits = 3; |
| v_rep_symbol = 0; |
| v_rep_count = 3; |
| } else if (v_table_entry == 18) { |
| v_n_extra_bits = 7; |
| v_rep_symbol = 0; |
| v_rep_count = 11; |
| } else { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| while (v_n_bits < v_n_extra_bits) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint8_t t_3 = *b_rptr_src++; |
| v_bits |= (((uint32_t)(t_3)) << v_n_bits); |
| v_n_bits += 8; |
| } |
| v_rep_count += ((v_bits) & ((1 << (v_n_extra_bits)) - 1)); |
| v_bits >>= v_n_extra_bits; |
| v_n_bits -= v_n_extra_bits; |
| while (v_rep_count > 0) { |
| if (v_i >= (v_n_lit + v_n_dist)) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT; |
| goto exit; |
| } |
| self->private_impl.f_code_lengths[v_i] = v_rep_symbol; |
| v_i += 1; |
| v_rep_count -= 1; |
| } |
| } |
| if (v_i != (v_n_lit + v_n_dist)) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_LENGTH_COUNT; |
| goto exit; |
| } |
| if (self->private_impl.f_code_lengths[256] == 0) { |
| status = PUFFS_FLATE__ERROR_MISSING_END_OF_BLOCK_CODE; |
| goto exit; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); |
| status = puffs_flate__flate_decoder__init_huff(self, 0, 0, v_n_lit, 257); |
| if (status) { |
| goto suspend; |
| } |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(7); |
| status = puffs_flate__flate_decoder__init_huff(self, 1, v_n_lit, |
| (v_n_lit + v_n_dist), 0); |
| if (status) { |
| goto suspend; |
| } |
| self->private_impl.f_bits = v_bits; |
| self->private_impl.f_n_bits = v_n_bits; |
| |
| goto ok; |
| ok: |
| self->private_impl.c_init_dynamic_huffman[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_init_dynamic_huffman[0].coro_susp_point = |
| coro_susp_point; |
| self->private_impl.c_init_dynamic_huffman[0].v_bits = v_bits; |
| self->private_impl.c_init_dynamic_huffman[0].v_n_bits = v_n_bits; |
| self->private_impl.c_init_dynamic_huffman[0].v_n_lit = v_n_lit; |
| self->private_impl.c_init_dynamic_huffman[0].v_n_dist = v_n_dist; |
| self->private_impl.c_init_dynamic_huffman[0].v_n_clen = v_n_clen; |
| self->private_impl.c_init_dynamic_huffman[0].v_i = v_i; |
| self->private_impl.c_init_dynamic_huffman[0].v_mask = v_mask; |
| self->private_impl.c_init_dynamic_huffman[0].v_table_entry = v_table_entry; |
| self->private_impl.c_init_dynamic_huffman[0].v_table_entry_n_bits = |
| v_table_entry_n_bits; |
| self->private_impl.c_init_dynamic_huffman[0].v_n_extra_bits = v_n_extra_bits; |
| self->private_impl.c_init_dynamic_huffman[0].v_rep_symbol = v_rep_symbol; |
| self->private_impl.c_init_dynamic_huffman[0].v_rep_count = v_rep_count; |
| |
| exit: |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rstart_src); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rend_src); |
| } |
| |
| return status; |
| |
| short_read_src: |
| if (a_src.buf && a_src.buf->closed && !a_src.limit.ptr_to_len) { |
| status = PUFFS_FLATE__ERROR_UNEXPECTED_EOF; |
| goto exit; |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| goto suspend; |
| } |
| |
| puffs_flate__status puffs_flate__flate_decoder__init_huff( |
| puffs_flate__flate_decoder* self, |
| uint32_t a_which, |
| uint32_t a_n_codes0, |
| uint32_t a_n_codes1, |
| uint32_t a_base_symbol) { |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint16_t v_counts[16]; |
| uint32_t v_i; |
| uint32_t v_remaining; |
| uint16_t v_offsets[16]; |
| uint32_t v_n_symbols; |
| uint32_t v_count; |
| uint16_t v_symbols[320]; |
| uint32_t v_min_cl; |
| uint32_t v_max_cl; |
| uint32_t v_initial_high_bits; |
| uint32_t v_prev_cl; |
| uint32_t v_prev_redirect_key; |
| uint32_t v_top; |
| uint32_t v_next_top; |
| uint32_t v_code; |
| uint32_t v_key; |
| uint32_t v_value; |
| uint32_t v_cl; |
| uint32_t v_tmp; |
| uint32_t v_redirect_key; |
| uint32_t v_j; |
| uint32_t v_reversed_key; |
| uint32_t v_symbol; |
| uint32_t v_high_bits; |
| uint32_t v_delta; |
| |
| memset(v_counts, 0, sizeof(v_counts)); |
| v_i = a_n_codes0; |
| while (v_i < a_n_codes1) { |
| if (v_counts[self->private_impl.f_code_lengths[v_i]] >= 320) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_counts[self->private_impl.f_code_lengths[v_i]] += 1; |
| v_i += 1; |
| } |
| if ((((uint32_t)(v_counts[0])) + a_n_codes0) == a_n_codes1) { |
| status = PUFFS_FLATE__ERROR_NO_HUFFMAN_CODES; |
| goto exit; |
| } |
| v_remaining = 1; |
| v_i = 1; |
| while (v_i <= 15) { |
| if (v_remaining > 1073741824) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_remaining <<= 1; |
| if (v_remaining < ((uint32_t)(v_counts[v_i]))) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_OVER_SUBSCRIBED; |
| goto exit; |
| } |
| v_remaining -= ((uint32_t)(v_counts[v_i])); |
| v_i += 1; |
| } |
| if (v_remaining != 0) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_CODE_UNDER_SUBSCRIBED; |
| goto exit; |
| } |
| memset(v_offsets, 0, sizeof(v_offsets)); |
| v_n_symbols = 0; |
| v_i = 1; |
| while (v_i <= 15) { |
| v_offsets[v_i] = ((uint16_t)(v_n_symbols)); |
| v_count = ((uint32_t)(v_counts[v_i])); |
| if (v_n_symbols > (320 - v_count)) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_n_symbols = (v_n_symbols + v_count); |
| v_i += 1; |
| } |
| if (v_n_symbols > 288) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| memset(v_symbols, 0, sizeof(v_symbols)); |
| v_i = a_n_codes0; |
| while (v_i < a_n_codes1) { |
| if (v_i < a_n_codes0) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| if (self->private_impl.f_code_lengths[v_i] != 0) { |
| if (v_offsets[self->private_impl.f_code_lengths[v_i]] >= 320) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_symbols[v_offsets[self->private_impl.f_code_lengths[v_i]]] = |
| ((uint16_t)((v_i - a_n_codes0))); |
| v_offsets[self->private_impl.f_code_lengths[v_i]] += 1; |
| } |
| v_i += 1; |
| } |
| v_min_cl = 1; |
| while (true) { |
| if (v_counts[v_min_cl] != 0) { |
| goto label_0_break; |
| } |
| if (v_min_cl >= 9) { |
| status = PUFFS_FLATE__ERROR_BAD_HUFFMAN_MINIMUM_CODE_LENGTH; |
| goto exit; |
| } |
| v_min_cl += 1; |
| } |
| label_0_break:; |
| v_max_cl = 15; |
| while (true) { |
| if (v_counts[v_max_cl] != 0) { |
| goto label_1_break; |
| } |
| if (v_max_cl <= 1) { |
| status = PUFFS_FLATE__ERROR_NO_HUFFMAN_CODES; |
| goto exit; |
| } |
| v_max_cl -= 1; |
| } |
| label_1_break:; |
| if (v_max_cl <= 9) { |
| self->private_impl.f_n_huffs_bits[a_which] = v_max_cl; |
| } else { |
| self->private_impl.f_n_huffs_bits[a_which] = 9; |
| } |
| v_i = 0; |
| if ((v_n_symbols != ((uint32_t)(v_offsets[v_max_cl]))) || |
| (v_n_symbols != ((uint32_t)(v_offsets[15])))) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| if ((a_n_codes0 + ((uint32_t)(v_symbols[0]))) >= 320) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_initial_high_bits = 512; |
| if (v_max_cl < 9) { |
| v_initial_high_bits = (((uint32_t)(1)) << v_max_cl); |
| } |
| v_prev_cl = ((uint32_t)( |
| self->private_impl |
| .f_code_lengths[a_n_codes0 + ((uint32_t)(v_symbols[0]))])); |
| v_prev_redirect_key = 4294967295; |
| v_top = 0; |
| v_next_top = 512; |
| v_code = 0; |
| v_key = 0; |
| v_value = 0; |
| while (true) { |
| if ((a_n_codes0 + ((uint32_t)(v_symbols[v_i]))) >= 320) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_cl = ((uint32_t)( |
| self->private_impl |
| .f_code_lengths[a_n_codes0 + ((uint32_t)(v_symbols[v_i]))])); |
| if (v_cl > v_prev_cl) { |
| v_code <<= (v_cl - v_prev_cl); |
| if (v_code >= 32768) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| } |
| v_prev_cl = v_cl; |
| v_key = v_code; |
| if (v_cl > 9) { |
| v_tmp = (v_cl - 9); |
| v_cl = v_tmp; |
| v_redirect_key = ((v_key >> v_tmp) & 511); |
| v_key = ((v_key) & ((1 << (v_tmp)) - 1)); |
| if (v_prev_redirect_key != v_redirect_key) { |
| v_prev_redirect_key = v_redirect_key; |
| v_remaining = (((uint32_t)(1)) << v_cl); |
| v_j = v_prev_cl; |
| while (v_j <= 15) { |
| if (v_remaining <= ((uint32_t)(v_counts[v_j]))) { |
| goto label_2_break; |
| } |
| v_remaining -= ((uint32_t)(v_counts[v_j])); |
| if (v_remaining > 1073741824) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_remaining <<= 1; |
| v_j += 1; |
| } |
| label_2_break:; |
| if ((v_j <= 9) || (15 < v_j)) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_tmp = (v_j - 9); |
| v_initial_high_bits = (((uint32_t)(1)) << v_tmp); |
| v_top = v_next_top; |
| if ((v_top + (((uint32_t)(1)) << v_tmp)) > 1234) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_next_top = (v_top + (((uint32_t)(1)) << v_tmp)); |
| v_redirect_key = |
| (((uint32_t)(puffs_flate__reverse8[v_redirect_key >> 1])) | |
| ((v_redirect_key & 1) << 8)); |
| self->private_impl.f_huffs[a_which][v_redirect_key] = |
| (268435465 | (v_top << 8) | (v_tmp << 4)); |
| } |
| } |
| if ((v_key >= 512) || (v_counts[v_prev_cl] <= 0)) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_counts[v_prev_cl] -= 1; |
| v_reversed_key = |
| (((uint32_t)(puffs_flate__reverse8[v_key >> 1])) | ((v_key & 1) << 8)); |
| v_reversed_key >>= (9 - v_cl); |
| v_symbol = ((uint32_t)(v_symbols[v_i])); |
| if (v_symbol == 256) { |
| v_value = (536870912 | v_cl); |
| } else if ((v_symbol < 256) && (a_which == 0)) { |
| v_value = (2147483648 | (v_symbol << 8) | v_cl); |
| } else if (v_symbol >= a_base_symbol) { |
| v_symbol -= a_base_symbol; |
| if (a_which == 0) { |
| v_value = (puffs_flate__lcode_magic_numbers[v_symbol & 31] | v_cl); |
| } else { |
| v_value = (puffs_flate__dcode_magic_numbers[v_symbol & 31] | v_cl); |
| } |
| } else { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| v_high_bits = v_initial_high_bits; |
| v_delta = (((uint32_t)(1)) << v_cl); |
| while (v_high_bits >= v_delta) { |
| v_high_bits -= v_delta; |
| if ((v_top + ((v_high_bits | v_reversed_key) & 511)) >= 1234) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| self->private_impl |
| .f_huffs[a_which][v_top + ((v_high_bits | v_reversed_key) & 511)] = |
| v_value; |
| } |
| v_i += 1; |
| if (v_i >= v_n_symbols) { |
| goto label_3_break; |
| } |
| v_code += 1; |
| if (v_code >= 32768) { |
| status = |
| PUFFS_FLATE__ERROR_INTERNAL_ERROR_INCONSISTENT_HUFFMAN_DECODER_STATE; |
| goto exit; |
| } |
| } |
| label_3_break:; |
| exit: |
| return status; |
| } |
| |
| puffs_flate__status puffs_flate__zlib_decoder__decode( |
| puffs_flate__zlib_decoder* self, |
| puffs_base__writer1 a_dst, |
| puffs_base__reader1 a_src) { |
| if (!self) { |
| return PUFFS_FLATE__ERROR_BAD_RECEIVER; |
| } |
| if (self->private_impl.magic != PUFFS_BASE__MAGIC) { |
| self->private_impl.status = PUFFS_FLATE__ERROR_INITIALIZER_NOT_CALLED; |
| } |
| if (self->private_impl.status < 0) { |
| return self->private_impl.status; |
| } |
| puffs_flate__status status = PUFFS_FLATE__STATUS_OK; |
| |
| uint16_t v_x; |
| uint32_t v_checksum; |
| puffs_flate__status v_z; |
| |
| uint8_t* b_wptr_dst = NULL; |
| uint8_t* b_wstart_dst = NULL; |
| uint8_t* b_wend_dst = NULL; |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wstart_dst = b_wptr_dst; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| uint8_t* b_rptr_src = NULL; |
| uint8_t* b_rstart_src = NULL; |
| uint8_t* b_rend_src = NULL; |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| b_rstart_src = b_rptr_src; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| |
| uint32_t coro_susp_point = self->private_impl.c_decode[0].coro_susp_point; |
| if (coro_susp_point) { |
| v_x = self->private_impl.c_decode[0].v_x; |
| v_checksum = self->private_impl.c_decode[0].v_checksum; |
| v_z = self->private_impl.c_decode[0].v_z; |
| } |
| switch (coro_susp_point) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(0); |
| |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(1); |
| uint16_t t_1; |
| if (PUFFS_BASE__LIKELY(b_rend_src - b_rptr_src >= 2)) { |
| t_1 = puffs_base__load_u16be(b_rptr_src); |
| b_rptr_src += 2; |
| } else { |
| self->private_impl.c_decode[0].scratch = 0; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(2); |
| while (true) { |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint32_t t_0 = self->private_impl.c_decode[0].scratch & 0xFF; |
| self->private_impl.c_decode[0].scratch >>= 8; |
| self->private_impl.c_decode[0].scratch <<= 8; |
| self->private_impl.c_decode[0].scratch |= ((uint64_t)(*b_rptr_src++)) |
| << (64 - t_0); |
| if (t_0 == 8) { |
| t_1 = self->private_impl.c_decode[0].scratch >> (64 - 16); |
| break; |
| } |
| t_0 += 8; |
| self->private_impl.c_decode[0].scratch |= ((uint64_t)(t_0)); |
| } |
| } |
| v_x = t_1; |
| if (((v_x >> 8) & 15) != 8) { |
| status = PUFFS_FLATE__ERROR_INVALID_ZLIB_COMPRESSION_METHOD; |
| goto exit; |
| } |
| if ((v_x >> 12) > 7) { |
| status = PUFFS_FLATE__ERROR_INVALID_ZLIB_COMPRESSION_WINDOW_SIZE; |
| goto exit; |
| } |
| if ((v_x & 32) != 0) { |
| status = PUFFS_FLATE__ERROR_TODO_UNSUPPORTED_ZLIB_PRESET_DICTIONARY; |
| goto exit; |
| } |
| if ((v_x % 31) != 0) { |
| status = PUFFS_FLATE__ERROR_INVALID_ZLIB_PARITY_CHECK; |
| goto exit; |
| } |
| v_checksum = 0; |
| while (true) { |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(3); |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| } |
| puffs_flate__status t_2 = puffs_flate__flate_decoder__decode( |
| &self->private_impl.f_flate, a_dst, a_src); |
| if (a_dst.buf) { |
| b_wptr_dst = a_dst.buf->ptr + a_dst.buf->wi; |
| b_wend_dst = b_wptr_dst; |
| if (!a_dst.buf->closed) { |
| size_t len = a_dst.buf->len - a_dst.buf->wi; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_wend_dst += len; |
| } |
| } |
| if (a_src.buf) { |
| b_rptr_src = a_src.buf->ptr + a_src.buf->ri; |
| size_t len = a_src.buf->wi - a_src.buf->ri; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len && (len > *lim->ptr_to_len)) { |
| len = *lim->ptr_to_len; |
| } |
| } |
| b_rend_src = b_rptr_src + len; |
| } |
| v_z = t_2; |
| v_checksum = puffs_flate__adler32__update( |
| &self->private_impl.f_adler, ((puffs_base__slice_u8){ |
| .ptr = b_wstart_dst, |
| .len = b_wptr_dst - b_wstart_dst, |
| })); |
| if (v_z == 0) { |
| goto label_0_break; |
| } |
| status = v_z; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT_MAYBE_SUSPEND(4); |
| } |
| label_0_break:; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(5); |
| uint32_t t_4; |
| if (PUFFS_BASE__LIKELY(b_rend_src - b_rptr_src >= 4)) { |
| t_4 = puffs_base__load_u32be(b_rptr_src); |
| b_rptr_src += 4; |
| } else { |
| self->private_impl.c_decode[0].scratch = 0; |
| PUFFS_BASE__COROUTINE_SUSPENSION_POINT(6); |
| while (true) { |
| if (PUFFS_BASE__UNLIKELY(b_rptr_src == b_rend_src)) { |
| goto short_read_src; |
| } |
| uint32_t t_3 = self->private_impl.c_decode[0].scratch & 0xFF; |
| self->private_impl.c_decode[0].scratch >>= 8; |
| self->private_impl.c_decode[0].scratch <<= 8; |
| self->private_impl.c_decode[0].scratch |= ((uint64_t)(*b_rptr_src++)) |
| << (64 - t_3); |
| if (t_3 == 24) { |
| t_4 = self->private_impl.c_decode[0].scratch >> (64 - 32); |
| break; |
| } |
| t_3 += 8; |
| self->private_impl.c_decode[0].scratch |= ((uint64_t)(t_3)); |
| } |
| } |
| if (v_checksum != t_4) { |
| status = PUFFS_FLATE__ERROR_CHECKSUM_MISMATCH; |
| goto exit; |
| } |
| |
| goto ok; |
| ok: |
| self->private_impl.c_decode[0].coro_susp_point = 0; |
| goto exit; |
| } |
| |
| goto suspend; |
| suspend: |
| self->private_impl.c_decode[0].coro_susp_point = coro_susp_point; |
| self->private_impl.c_decode[0].v_x = v_x; |
| self->private_impl.c_decode[0].v_checksum = v_checksum; |
| self->private_impl.c_decode[0].v_z = v_z; |
| |
| exit: |
| if (a_dst.buf) { |
| size_t n = b_wptr_dst - (a_dst.buf->ptr + a_dst.buf->wi); |
| a_dst.buf->wi += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_dst.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wstart_dst); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_wend_dst); |
| } |
| if (a_src.buf) { |
| size_t n = b_rptr_src - (a_src.buf->ptr + a_src.buf->ri); |
| a_src.buf->ri += n; |
| puffs_base__limit1* lim; |
| for (lim = &a_src.limit; lim; lim = lim->next) { |
| if (lim->ptr_to_len) { |
| *lim->ptr_to_len -= n; |
| } |
| } |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rstart_src); |
| PUFFS_BASE__IGNORE_POTENTIALLY_UNUSED_VARIABLE(b_rend_src); |
| } |
| |
| self->private_impl.status = status; |
| return status; |
| |
| short_read_src: |
| if (a_src.buf && a_src.buf->closed && !a_src.limit.ptr_to_len) { |
| status = PUFFS_FLATE__ERROR_UNEXPECTED_EOF; |
| goto exit; |
| } |
| status = PUFFS_FLATE__SUSPENSION_SHORT_READ; |
| goto suspend; |
| } |
| |
| uint32_t puffs_flate__adler32__update(puffs_flate__adler32* self, |
| puffs_base__slice_u8 a_x) { |
| uint32_t v_s1; |
| uint32_t v_s2; |
| puffs_base__slice_u8 v_remaining; |
| |
| v_s1 = ((self->private_impl.f_state) & ((1 << (16)) - 1)); |
| v_s2 = ((self->private_impl.f_state) >> (32 - (16))); |
| while (((uint64_t)(a_x.len)) > 0) { |
| v_remaining = ((puffs_base__slice_u8){}); |
| if (((uint64_t)(a_x.len)) > 5552) { |
| v_remaining = puffs_base__slice_u8__subslice_i(a_x, 5552); |
| a_x = puffs_base__slice_u8__subslice_j(a_x, 5552); |
| } |
| { |
| puffs_base__slice_u8 i_slice_p = a_x; |
| uint8_t* v_p = i_slice_p.ptr; |
| uint8_t* i_end0_p = i_slice_p.ptr + (i_slice_p.len / 8) * 8; |
| while (v_p < i_end0_p) { |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| } |
| uint8_t* i_end1_p = i_slice_p.ptr + i_slice_p.len; |
| while (v_p < i_end1_p) { |
| v_s1 += ((uint32_t)(*v_p)); |
| v_s2 += v_s1; |
| v_p++; |
| } |
| } |
| v_s1 %= 65521; |
| v_s2 %= 65521; |
| a_x = v_remaining; |
| } |
| self->private_impl.f_state = (((v_s2 & 65535) << 16) | (v_s1 & 65535)); |
| return self->private_impl.f_state; |
| } |