21#ifdef ZXC_FUNCTION_SUFFIX
22#define ZXC_CAT_IMPL(x, y) x##y
23#define ZXC_CAT(x, y) ZXC_CAT_IMPL(x, y)
24#define zxc_decompress_chunk_wrapper ZXC_CAT(zxc_decompress_chunk_wrapper, ZXC_FUNCTION_SUFFIX)
25#define zxc_decompress_chunk_wrapper_dict \
26 ZXC_CAT(zxc_decompress_chunk_wrapper_dict, ZXC_FUNCTION_SUFFIX)
27#define zxc_decompress_chunk_wrapper_safe \
28 ZXC_CAT(zxc_decompress_chunk_wrapper_safe, ZXC_FUNCTION_SUFFIX)
29#define zxc_huf_decode_section ZXC_CAT(zxc_huf_decode_section, ZXC_FUNCTION_SUFFIX)
30#define zxc_huf_decode_section_dict ZXC_CAT(zxc_huf_decode_section_dict, ZXC_FUNCTION_SUFFIX)
33#include "../../include/zxc_error.h"
36#if defined(ZXC_USE_NEON64) || defined(ZXC_USE_NEON32) || defined(ZXC_USE_AVX2) || \
37 defined(ZXC_USE_AVX512)
43static const ZXC_ALIGN(32) uint8_t zxc_overlap_masks32[32][32] = {
44 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
46 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
47 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
48 {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
49 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1},
50 {0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0,
51 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1},
52 {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
53 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
54 {0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0,
55 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1},
56 {0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3,
57 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1},
58 {0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1,
59 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3},
60 {0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7,
61 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7},
62 {0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4, 5, 6,
63 7, 8, 0, 1, 2, 3, 4, 5, 6, 7, 8, 0, 1, 2, 3, 4},
64 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
65 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1},
66 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4,
67 5, 6, 7, 8, 9, 10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
68 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3,
69 4, 5, 6, 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 5, 6, 7},
70 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2,
71 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0, 1, 2, 3, 4, 5},
72 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1,
73 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0, 1, 2, 3},
74 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0,
75 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0, 1},
76 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
77 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15},
78 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
79 16, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14},
80 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
81 16, 17, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13},
82 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
83 16, 17, 18, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
84 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
85 16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
86 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
87 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
88 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
89 16, 17, 18, 19, 20, 21, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
90 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
91 16, 17, 18, 19, 20, 21, 22, 0, 1, 2, 3, 4, 5, 6, 7, 8},
92 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
93 16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7},
94 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
95 16, 17, 18, 19, 20, 21, 22, 23, 24, 0, 1, 2, 3, 4, 5, 6},
96 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
97 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5},
98 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
99 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 0, 1, 2, 3, 4},
100 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
101 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 1, 2, 3},
102 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
103 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 0, 1, 2},
104 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
105 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0, 1},
106 {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
107 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 0}
117static const uint8_t
zxc_overlap_strides32[32] = {32, 32, 32, 30, 32, 30, 30, 28, 32, 27, 30,
118 22, 24, 26, 28, 30, 32, 17, 18, 19, 20, 21,
119 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
147#if defined(ZXC_USE_NEON64)
149 tbl.val[0] = vld1q_u8(dst - off);
150 tbl.val[1] = vld1q_u8(dst - off + 16);
151 const uint8x16_t pat_lo = vqtbl2q_u8(tbl, vld1q_u8(zxc_overlap_masks32[off]));
152 const uint8x16_t pat_hi = vqtbl2q_u8(tbl, vld1q_u8(zxc_overlap_masks32[off] + 16));
154 vst1q_u8(dst + copied, pat_lo);
155 vst1q_u8(dst + copied + 16, pat_hi);
157 }
while (copied < ml);
159#elif defined(ZXC_USE_NEON32)
163 tbl.val[0] = vld1_u8(dst - off);
164 tbl.val[1] = vld1_u8(dst - off + 8);
165 tbl.val[2] = vld1_u8(dst - off + 16);
166 tbl.val[3] = vld1_u8(dst - off + 24);
167 const uint8_t*
const m = zxc_overlap_masks32[off];
168 const uint8x8_t p0 = vtbl4_u8(tbl, vld1_u8(m));
169 const uint8x8_t p1 = vtbl4_u8(tbl, vld1_u8(m + 8));
170 const uint8x8_t p2 = vtbl4_u8(tbl, vld1_u8(m + 16));
171 const uint8x8_t p3 = vtbl4_u8(tbl, vld1_u8(m + 24));
173 vst1_u8(dst + copied, p0);
174 vst1_u8(dst + copied + 8, p1);
175 vst1_u8(dst + copied + 16, p2);
176 vst1_u8(dst + copied + 24, p3);
178 }
while (copied < ml);
180#elif defined(ZXC_USE_AVX2) || defined(ZXC_USE_AVX512)
183 const __m128i t0 = _mm_loadu_si128((
const __m128i*)(dst - off));
184 const __m128i t1 = _mm_loadu_si128((
const __m128i*)(dst - off + 16));
185 const __m128i sixteen = _mm_set1_epi8(16);
186 const __m128i m_lo = _mm_load_si128((
const __m128i*)zxc_overlap_masks32[off]);
187 const __m128i m_hi = _mm_load_si128((
const __m128i*)(zxc_overlap_masks32[off] + 16));
188 const __m128i pat_lo =
189 _mm_blendv_epi8(_mm_shuffle_epi8(t0, m_lo),
190 _mm_shuffle_epi8(t1, _mm_sub_epi8(m_lo, sixteen)), _mm_slli_epi16(m_lo, 3));
191 const __m128i pat_hi =
192 _mm_blendv_epi8(_mm_shuffle_epi8(t0, m_hi),
193 _mm_shuffle_epi8(t1, _mm_sub_epi8(m_hi, sixteen)), _mm_slli_epi16(m_hi, 3));
195 _mm_storeu_si128((__m128i*)(dst + copied), pat_lo);
196 _mm_storeu_si128((__m128i*)(dst + copied + 16), pat_hi);
198 }
while (copied < ml);
203 const uint8_t* src = dst - off;
206 for (
size_t i = 0; i < 32; i++) {
208 if (++k == off) k = 0;
214 }
while (copied < ml);
240#if defined(ZXC_USE_NEON64)
241 const uint8x16_t s0 = vld1q_u8(dst - off);
242 vst1q_u8(dst, vqtbl1q_u8(s0, vld1q_u8(zxc_overlap_masks32[off])));
243 if (UNLIKELY(ml > 16)) {
246 tbl.val[1] = vld1q_u8(dst - off + 16);
247 vst1q_u8(dst + 16, vqtbl2q_u8(tbl, vld1q_u8(zxc_overlap_masks32[off] + 16)));
250#elif defined(ZXC_USE_NEON32)
252 lo_tbl.val[0] = vld1_u8(dst - off);
253 lo_tbl.val[1] = vld1_u8(dst - off + 8);
254 const uint8_t*
const m = zxc_overlap_masks32[off];
255 vst1_u8(dst, vtbl2_u8(lo_tbl, vld1_u8(m)));
256 vst1_u8(dst + 8, vtbl2_u8(lo_tbl, vld1_u8(m + 8)));
257 if (UNLIKELY(ml > 16)) {
259 tbl.val[0] = lo_tbl.val[0];
260 tbl.val[1] = lo_tbl.val[1];
261 tbl.val[2] = vld1_u8(dst - off + 16);
262 tbl.val[3] = vld1_u8(dst - off + 24);
263 vst1_u8(dst + 16, vtbl4_u8(tbl, vld1_u8(m + 16)));
264 vst1_u8(dst + 24, vtbl4_u8(tbl, vld1_u8(m + 24)));
267#elif defined(ZXC_USE_AVX2) || defined(ZXC_USE_AVX512)
270 const __m128i t0 = _mm_loadu_si128((
const __m128i*)(dst - off));
273 _mm_shuffle_epi8(t0, _mm_load_si128((
const __m128i*)zxc_overlap_masks32[off])));
274 if (UNLIKELY(ml > 16)) {
275 const __m128i t1 = _mm_loadu_si128((
const __m128i*)(dst - off + 16));
276 const __m128i m_hi = _mm_load_si128((
const __m128i*)(zxc_overlap_masks32[off] + 16));
278 (__m128i*)(dst + 16),
279 _mm_blendv_epi8(_mm_shuffle_epi8(t0, m_hi),
280 _mm_shuffle_epi8(t1, _mm_sub_epi8(m_hi, _mm_set1_epi8(16))),
281 _mm_slli_epi16(m_hi, 3)));
285 const uint8_t* src = dst - off;
286 const size_t n = (ml > 16) ? 32 : 16;
288 for (
size_t i = 0; i < n; i++) {
290 if (++k == off) k = 0;
311#if defined(ZXC_USE_AVX2) || defined(ZXC_USE_AVX512)
312 const __m256i v = _mm256_set1_epi8((
char)
byte);
313 _mm256_storeu_si256((__m256i*)dst, v);
314 if (UNLIKELY(ml > 32)) {
316 const uint8_t*
const last = dst + ml - 32;
319 _mm256_storeu_si256((__m256i*)p, v);
322#elif defined(ZXC_USE_SSE2)
323 const __m128i v = _mm_set1_epi8((
char)
byte);
324 _mm_storeu_si128((__m128i*)dst, v);
325 _mm_storeu_si128((__m128i*)(dst + 16), v);
326 if (UNLIKELY(ml > 32)) {
328 const uint8_t*
const last = dst + ml - 32;
331 _mm_storeu_si128((__m128i*)p, v);
332 _mm_storeu_si128((__m128i*)(p + 16), v);
335#elif defined(ZXC_USE_NEON64) || defined(ZXC_USE_NEON32)
336 const uint8x16_t v = vdupq_n_u8(
byte);
338 vst1q_u8(dst + 16, v);
339 if (UNLIKELY(ml > 32)) {
341 const uint8_t*
const last = dst + ml - 32;
349 ZXC_MEMSET(dst,
byte, ml);
374 if (UNLIKELY(len > 32)) {
375 size_t rem = len - 32;
404 const uint8_t* RESTRICT src,
434 const uint8_t* match_src = d_ptr - off;
435 if (LIKELY(off >= 32)) {
437 }
else if (off == 1) {
460 const uint32_t off,
const uint64_t ml) {
461 const uint8_t* match_src = d_ptr - off;
462 if (LIKELY(off >= 32)) {
464 }
else if (off == 1) {
504 const size_t off,
const size_t ml) {
506 ZXC_MEMCPY(d_ptr, match_src, ml);
507 }
else if (ml < 16) {
508 for (
size_t i = 0; i < ml; i++) d_ptr[i] = match_src[i];
511 ZXC_MEMCPY(d_ptr, match_src, n);
512 while (n <= ml - n) {
513 ZXC_MEMCPY(d_ptr + n, d_ptr, n);
516 ZXC_MEMCPY(d_ptr + n, d_ptr, ml - n);
527#define DECODE_MATCH_SAFE(ml, off, COPY) \
529 if (UNLIKELY((size_t)(d_ptr - d_floor) < (off))) return ZXC_ERROR_BAD_OFFSET; \
530 COPY(d_ptr, off, ml); \
536#define DECODE_MATCH_FAST(ml, off, COPY) \
538 COPY(d_ptr, off, ml); \
553#define GLO_OFF8 (gh.enc_off == 1)
568#define DECODE_GLO_SEQ(LL, ML, OFF, RESERVE, N_REM, DECODE, ON_FAIL) \
570 uint64_t ll = (LL); \
571 uint64_t ml = (ML); \
572 if (UNLIKELY(ll == ZXC_TOKEN_LL_MASK)) { \
573 ll += zxc_read_varint(&e_ptr, e_end); \
574 const uint64_t reserve = (RESERVE); \
578 if (UNLIKELY(ll + reserve > (size_t)(l_end - l_ptr) || \
579 ll + ml + ZXC_LZ_MIN_MATCH_LEN + \
580 (N_REM) * ZXC_GLO_MAX_INLINE_OUT_PER_SEQ + ZXC_PAD_SIZE > \
581 (size_t)(d_end - d_ptr))) \
583 zxc_decode_copy_literals(d_ptr, l_ptr, ll); \
586 zxc_copy16(d_ptr, l_ptr); \
590 if (UNLIKELY(ml == ZXC_TOKEN_ML_MASK)) { \
591 ml += zxc_read_varint(&e_ptr, e_end); \
593 if (UNLIKELY(ml + ZXC_LZ_MIN_MATCH_LEN + (N_REM) * ZXC_GLO_MAX_INLINE_OUT_PER_SEQ + \
595 (size_t)(d_end - d_ptr))) \
598 ml += ZXC_LZ_MIN_MATCH_LEN; \
599 DECODE(ml, OFF, zxc_decode_copy_match_glo); \
610#define DECODE_GLO_BATCH_4X(DECODE, ON_FAIL) \
612 uint32_t tokens = zxc_le32(t_ptr); \
613 t_ptr += sizeof(uint32_t); \
616 uint64_t x = zxc_le32(o_ptr); \
617 o_ptr += sizeof(uint32_t); \
618 x = (x | (x << 16)) & 0x0000FFFF0000FFFFULL; \
619 offs = (x | (x << 8)) & 0x00FF00FF00FF00FFULL; \
621 offs = zxc_le64(o_ptr); \
622 o_ptr += sizeof(uint64_t); \
624 DECODE_GLO_SEQ((tokens & 0x0F0) >> 4, (tokens & 0x00F), \
625 ZXC_LZ_OFFSET_BIAS + (uint32_t)(offs & 0xFFFF), \
626 ((tokens >> 12) & 0xF) + ((tokens >> 20) & 0xF) + (tokens >> 28), 3U, \
628 DECODE_GLO_SEQ((tokens & 0x0F000) >> 12, (tokens & 0x00F00) >> 8, \
629 ZXC_LZ_OFFSET_BIAS + (uint32_t)((offs >> 16) & 0xFFFF), \
630 ((tokens >> 20) & 0xF) + (tokens >> 28), 2U, DECODE, ON_FAIL); \
631 DECODE_GLO_SEQ((tokens & 0x0F00000) >> 20, (tokens & 0x00F0000) >> 16, \
632 ZXC_LZ_OFFSET_BIAS + (uint32_t)((offs >> 32) & 0xFFFF), (tokens >> 28), 1U, \
634 DECODE_GLO_SEQ((tokens >> 28), (tokens >> 24) & 0x0F, \
635 ZXC_LZ_OFFSET_BIAS + (uint32_t)(offs >> 48), 0, 0U, DECODE, ON_FAIL); \
644#define DECODE_GHI_SEQ(S, RESERVE, N_REM, DECODE, ON_FAIL) \
646 uint64_t ll = (S) >> 24; \
647 const uint32_t mb = ((S) >> 16) & 0xFF; \
648 uint64_t ml = mb + ZXC_LZ_MIN_MATCH_LEN; \
649 if (UNLIKELY(ll == ZXC_SEQ_LL_MASK)) { \
650 ll += zxc_read_varint(&extras_ptr, extras_end); \
651 const uint64_t reserve = (RESERVE); \
653 if (UNLIKELY(ll + reserve > (size_t)(l_end - l_ptr) || \
654 ll + ml + (N_REM) * ZXC_GHI_MAX_INLINE_OUT_PER_SEQ + ZXC_PAD_SIZE > \
655 (size_t)(d_end - d_ptr))) \
658 if (UNLIKELY(mb == ZXC_SEQ_ML_MASK)) { \
659 ml += zxc_read_varint(&extras_ptr, extras_end); \
660 if (UNLIKELY(ll + ml + (N_REM) * ZXC_GHI_MAX_INLINE_OUT_PER_SEQ + ZXC_PAD_SIZE > \
661 (size_t)(d_end - d_ptr))) \
664 const uint32_t off = ((S) & 0xFFFF) + ZXC_LZ_OFFSET_BIAS; \
666 zxc_decode_copy_literals(d_ptr, l_ptr, ll); \
669 DECODE(ml, off, zxc_decode_copy_match); \
677#define DECODE_GHI_BATCH_4X(DECODE, ON_FAIL, PREFETCH) \
679 uint32_t s1 = zxc_le32(seq_ptr); \
680 uint32_t s2 = zxc_le32(seq_ptr + sizeof(uint32_t)); \
681 uint32_t s3 = zxc_le32(seq_ptr + 2 * sizeof(uint32_t)); \
682 uint32_t s4 = zxc_le32(seq_ptr + 3 * sizeof(uint32_t)); \
683 seq_ptr += 4 * sizeof(uint32_t); \
685 DECODE_GHI_SEQ(s1, (s2 >> 24) + (s3 >> 24) + (s4 >> 24), 3U, DECODE, ON_FAIL); \
686 DECODE_GHI_SEQ(s2, (s3 >> 24) + (s4 >> 24), 2U, DECODE, ON_FAIL); \
687 DECODE_GHI_SEQ(s3, (s4 >> 24), 1U, DECODE, ON_FAIL); \
688 DECODE_GHI_SEQ(s4, 0, 0U, DECODE, ON_FAIL); \
707 if (LIKELY(ctx->pivco_scratch))
return ZXC_OK;
712 const uint8_t* RESTRICT payload,
714 const size_t required_size) {
716 if (UNLIKELY(arc !=
ZXC_OK))
return arc;
717 if (UNLIKELY(ctx->lit_buffer_cap < required_size +
ZXC_PAD_SIZE ||
725 const uint8_t* RESTRICT payload,
727 const size_t required_size) {
730 if (UNLIKELY(arc !=
ZXC_OK))
return arc;
731 if (UNLIKELY(ctx->lit_buffer_cap < required_size +
ZXC_PAD_SIZE ||
735 &ctx->dict_huf->tree, ctx->pivco_scratch);
739 const uint8_t* RESTRICT payload,
740 const size_t psize,
const size_t n_tok) {
742 if (UNLIKELY(arc !=
ZXC_OK))
return arc;
743 if (UNLIKELY(n_tok +
ZXC_PAD_SIZE > ctx->tok_buffer_cap ||
750 const uint8_t* RESTRICT src,
size_t src_size,
751 uint8_t* RESTRICT dst,
size_t dst_capacity);
753 const uint8_t* RESTRICT src,
754 size_t src_size, uint8_t* RESTRICT dst,
755 size_t dst_capacity);
757 const uint8_t* RESTRICT src,
758 size_t src_size, uint8_t* RESTRICT dst,
759 size_t dst_capacity);
790 const uint8_t* RESTRICT src,
791 const size_t src_size, uint8_t* RESTRICT dst,
792 const size_t dst_capacity,
const int safe,
793 const int has_dict,
const int tok_entropy) {
797 const size_t dict_size = has_dict ? ctx->dict_size : 0;
811 if (!tok_entropy && UNLIKELY(gh.
enc_tok == ZXC_SECTION_ENCODING_HUFFMAN)) {
812 if (safe)
return zxc_decode_block_glo_entropy_safe(ctx, src, src_size, dst, dst_capacity);
814 return zxc_decode_block_glo_entropy_dict(ctx, src, src_size, dst, dst_capacity);
818 const uint8_t* p_data = src + (size_t)hdr_sz;
819 const uint8_t* p_curr = p_data;
822 const uint8_t* l_ptr;
823 const uint8_t* l_end;
824 uint8_t* rle_buf = NULL;
826 size_t lit_stream_size = lit_comp;
830 if (gh.
enc_lit == ZXC_SECTION_ENCODING_HUFFMAN ||
831 gh.
enc_lit == ZXC_SECTION_ENCODING_HUFFMAN_DICT) {
832 if (UNLIKELY(lit_stream_size > (
size_t)(src + src_size - p_curr)))
834 if (required_size == 0) {
838 if (UNLIKELY(required_size > dst_capacity || required_size > SIZE_MAX -
ZXC_PAD_SIZE))
841 (gh.
enc_lit == ZXC_SECTION_ENCODING_HUFFMAN)
842 ? zxc_decode_lit_pivco(ctx, p_curr, lit_stream_size, required_size)
843 : zxc_decode_lit_pivco_dict(ctx, p_curr, lit_stream_size, required_size);
844 if (UNLIKELY(rc !=
ZXC_OK))
return rc;
845 l_ptr = ctx->lit_buffer;
846 l_end = ctx->lit_buffer + required_size;
848 }
else if (gh.
enc_lit == ZXC_SECTION_ENCODING_RLE) {
849 if (required_size > 0) {
850 if (UNLIKELY(required_size > dst_capacity || required_size > SIZE_MAX -
ZXC_PAD_SIZE))
858 rle_buf = ctx->lit_buffer;
859 if (UNLIKELY(!rle_buf || lit_stream_size > (
size_t)(src + src_size - p_curr)))
862 const uint8_t* r_ptr = p_curr;
863 const uint8_t* r_end = r_ptr + lit_stream_size;
864 uint8_t* w_ptr = rle_buf;
865 const uint8_t*
const w_end = rle_buf + required_size;
867 while (r_ptr < r_end && w_ptr < w_end) {
868 uint8_t token = *r_ptr++;
872 const uint32_t len = (uint32_t)token + 1;
873 if (UNLIKELY(w_ptr + len > w_end || r_ptr + len > r_end))
879 if (LIKELY(r_ptr + 32 <= r_end)) {
883 if (UNLIKELY(len > 32)) {
888 zxc_copy32(w_ptr + len - 32, r_ptr + len - 32);
889 }
else if (len <= 96) {
891 zxc_copy32(w_ptr + len - 32, r_ptr + len - 32);
895 zxc_copy32(w_ptr + len - 32, r_ptr + len - 32);
900 ZXC_MEMCPY(w_ptr, r_ptr, len);
908 if (UNLIKELY(w_ptr + len > w_end || r_ptr >= r_end))
910 ZXC_MEMSET(w_ptr, *r_ptr++, len);
916 l_end = rle_buf + required_size;
922 }
else if (gh.
enc_lit == ZXC_SECTION_ENCODING_RAW) {
924 l_end = p_curr + lit_stream_size;
929 p_curr += lit_stream_size;
934 const size_t sz_tokens = tok_comp;
935 const uint64_t sz_offsets =
GLO_OFF8 ? (uint64_t)gh.
n_sequences : (uint64_t)gh.n_sequences * 2;
937 const size_t payload_avail = (size_t)(src + src_size - p_data);
938 const uint64_t consumed = (uint64_t)lit_stream_size + (uint64_t)sz_tokens + sz_offsets;
940 const size_t sz_extras = payload_avail - (size_t)consumed;
951 const uint8_t* o_ptr = p_curr + sz_tokens;
952 const uint8_t* e_ptr = o_ptr + (size_t)sz_offsets;
953 const uint8_t*
const e_end = e_ptr + sz_extras;
955 const uint8_t* RESTRICT t_ptr;
963 const int rc = zxc_decode_tok_pivco(ctx, p_curr, sz_tokens, gh.
n_sequences);
964 if (UNLIKELY(rc !=
ZXC_OK))
return rc;
965 t_ptr = ctx->tok_buffer;
968 uint8_t* d_ptr = dst;
969 const uint8_t*
const d_end = dst + dst_capacity;
971 const uint8_t*
const d_floor = dst - dict_size;
975 const uint8_t*
const d_end_safe =
980 const size_t glo_sz_lit = (size_t)(l_end - l_ptr);
983 const uint8_t*
const l_end_safe_4x =
984 (glo_sz_lit > glo_margin_4x) ? l_end - glo_margin_4x : l_ptr;
985 const uint8_t*
const l_end_safe_1x =
986 (glo_sz_lit > glo_margin_1x) ? l_end - glo_margin_1x : l_ptr;
994 const size_t off_span =
GLO_OFF8 ? (1U << 8) : (1U << 16);
995 const size_t span = (dict_size >= off_span) ? 0 : off_span - dict_size;
996 const uint8_t*
const d_bounds = (span >= dst_capacity) ? d_end : dst + span;
1001 while (n_seq >= 4 && d_ptr < d_end_safe && l_ptr < l_end_safe_4x && d_ptr < d_bounds) {
1002 const uint8_t*
const t_save = t_ptr;
1003 const uint8_t*
const o_save = o_ptr;
1004 const uint8_t*
const e_save = e_ptr;
1005 uint8_t*
const d_save = d_ptr;
1006 const uint8_t*
const l_save = l_ptr;
1019 while (n_seq >= 4 && d_ptr < d_end_safe && l_ptr < l_end_safe_4x && d_ptr < d_bounds) {
1026 while (n_seq >= 4 && d_ptr < d_end_safe && l_ptr < l_end_safe_4x) {
1027 const uint8_t*
const t_save = t_ptr;
1028 const uint8_t*
const o_save = o_ptr;
1029 const uint8_t*
const e_save = e_ptr;
1030 uint8_t*
const d_save = d_ptr;
1031 const uint8_t*
const l_save = l_ptr;
1044 while (n_seq >= 4 && d_ptr < d_end_safe && l_ptr < l_end_safe_4x) {
1053 while (n_seq > 0 && d_ptr < d_end_safe && l_ptr < l_end_safe_1x) {
1055 const uint8_t* t_save = t_ptr;
1056 const uint8_t* o_save = o_ptr;
1057 const uint8_t* e_save = e_ptr;
1059 uint8_t token = *t_ptr++;
1067 o_ptr +=
sizeof(uint16_t);
1072 if (UNLIKELY(l_ptr + ll > l_end)) {
1083 if (UNLIKELY(ll + ml +
ZXC_PAD_SIZE > (
size_t)(d_end - d_ptr))) {
1101 if (UNLIKELY(d_ptr < d_bounds && (
size_t)(d_ptr - d_floor) < offset))
1113 uint8_t token = *t_ptr++;
1121 o_ptr +=
sizeof(uint16_t);
1128 if (UNLIKELY(ll + ml > (
size_t)(d_end - d_ptr) || l_ptr + ll > l_end))
1130 ZXC_MEMCPY(d_ptr, l_ptr, ll);
1135 const uint8_t* match_src = d_ptr - offset;
1147 const size_t remaining_literals = (size_t)(l_end - l_ptr);
1148 if (UNLIKELY(remaining_literals > (
size_t)(d_end - d_ptr)))
return ZXC_ERROR_OVERFLOW;
1149 ZXC_MEMCPY(d_ptr, l_ptr, remaining_literals);
1150 d_ptr += remaining_literals;
1152 return (
int)(d_ptr - dst);
1176 const uint8_t* RESTRICT src,
1177 const size_t src_size, uint8_t* RESTRICT dst,
1178 const size_t dst_capacity,
const int safe,
1179 const int has_dict) {
1183 const size_t dict_size = has_dict ? ctx->dict_size : 0;
1186 if (UNLIKELY(gh.
enc_lit != ZXC_SECTION_ENCODING_RAW || gh.
enc_tok != 0))
1190 const uint8_t* p_curr = p_data;
1196 const uint64_t sz_seqs = (uint64_t)gh.
n_sequences *
sizeof(uint32_t);
1198 const size_t payload_avail = (size_t)(src + src_size - p_data);
1199 const uint64_t consumed = (uint64_t)sz_lit + sz_seqs;
1201 const size_t sz_exts = payload_avail - (size_t)consumed;
1207 const uint8_t* l_ptr = p_curr;
1208 const uint8_t* l_end = l_ptr + sz_lit;
1211 const uint8_t* seq_ptr = p_curr;
1212 const uint8_t* extras_ptr = p_curr + (size_t)sz_seqs;
1213 const uint8_t*
const extras_end = extras_ptr + sz_exts;
1215 uint8_t* d_ptr = dst;
1216 const uint8_t*
const d_end = dst + dst_capacity;
1218 const uint8_t*
const d_floor = dst - dict_size;
1219 const uint8_t*
const d_end_safe =
1223 const uint8_t*
const d_end_fast =
1230 const uint8_t*
const l_end_safe_4x = (sz_lit > ghi_margin_4x) ? l_end - ghi_margin_4x : l_ptr;
1231 const uint8_t*
const l_end_safe_1x = (sz_lit > ghi_margin_1x) ? l_end - ghi_margin_1x : l_ptr;
1237 const size_t off_span = 1U << 16;
1238 const size_t span = (dict_size >= off_span) ? 0 : off_span - dict_size;
1239 const uint8_t*
const d_bounds = (span >= dst_capacity) ? d_end : dst + span;
1246 while (n_seq >= 4 && d_ptr < d_end_fast && l_ptr < l_end_safe_4x && d_ptr < d_bounds) {
1247 const uint8_t*
const t_save = seq_ptr;
1248 const uint8_t*
const e_save = extras_ptr;
1249 uint8_t*
const d_save = d_ptr;
1250 const uint8_t*
const l_save = l_ptr;
1256 extras_ptr = e_save;
1262 while (n_seq >= 4 && d_ptr < d_end_fast && l_ptr < l_end_safe_4x && d_ptr < d_bounds) {
1268 while (n_seq > 0 && d_ptr < d_end_safe && d_ptr < d_bounds) {
1270 seq_ptr +=
sizeof(uint32_t);
1272 uint64_t ll = seq >> 24;
1275 uint32_t m_bits = (seq >> 16) & 0xFF;
1283 if (UNLIKELY(ll + ml +
ZXC_PAD_SIZE > (
size_t)(d_end - d_ptr) ||
1287 ZXC_MEMCPY(d_ptr, l_ptr, ll);
1293 const uint8_t* match_src = d_ptr - offset;
1308 while (n_seq >= 4 && d_ptr < d_end_fast && l_ptr < l_end_safe_4x) {
1309 const uint8_t*
const t_save = seq_ptr;
1310 const uint8_t*
const e_save = extras_ptr;
1311 uint8_t*
const d_save = d_ptr;
1312 const uint8_t*
const l_save = l_ptr;
1319 extras_ptr = e_save;
1325 while (n_seq >= 4 && d_ptr < d_end_fast && l_ptr < l_end_safe_4x) {
1332 while (n_seq > 0 && d_ptr < d_end_safe && l_ptr < l_end_safe_1x) {
1334 const uint8_t* seq_save = seq_ptr;
1335 const uint8_t* ext_save = extras_ptr;
1337 const uint32_t seq =
zxc_le32(seq_ptr);
1338 seq_ptr +=
sizeof(uint32_t);
1340 uint64_t ll = seq >> 24;
1343 if (UNLIKELY(l_ptr + ll > l_end)) {
1345 extras_ptr = ext_save;
1350 uint32_t m_bits = (seq >> 16) & 0xFF;
1355 if (UNLIKELY(ll + ml +
ZXC_PAD_SIZE > (
size_t)(d_end - d_ptr) ||
1358 extras_ptr = ext_save;
1367 if (UNLIKELY(d_ptr < d_bounds && (
size_t)(d_ptr - d_floor) < offset))
1380 seq_ptr +=
sizeof(uint32_t);
1382 uint64_t ll = seq >> 24;
1385 uint32_t m_bits = (seq >> 16) & 0xFF;
1390 if (UNLIKELY(ll + ml > (
size_t)(d_end - d_ptr) || l_ptr + ll > l_end))
1392 ZXC_MEMCPY(d_ptr, l_ptr, ll);
1397 const uint8_t* match_src = d_ptr - offset;
1409 const size_t remaining_literals = (size_t)(l_end - l_ptr);
1410 if (UNLIKELY(remaining_literals > (
size_t)(d_end - d_ptr)))
return ZXC_ERROR_OVERFLOW;
1411 ZXC_MEMCPY(d_ptr, l_ptr, remaining_literals);
1412 d_ptr += remaining_literals;
1414 return (
int)(d_ptr - dst);
1423 const uint8_t* RESTRICT src,
1424 const size_t src_size, uint8_t* RESTRICT dst,
1425 const size_t dst_capacity) {
1430 const uint8_t* RESTRICT src,
1431 const size_t src_size,
1432 uint8_t* RESTRICT dst,
1433 const size_t dst_capacity) {
1438 const uint8_t* RESTRICT src,
1439 const size_t src_size,
1440 uint8_t* RESTRICT dst,
1441 const size_t dst_capacity) {
1459 const size_t src_size, uint8_t* RESTRICT dst,
1460 const size_t dst_capacity) {
1477 const size_t src_size, uint8_t* RESTRICT dst,
1478 const size_t dst_capacity) {
1497 const uint8_t* RESTRICT src,
1498 const size_t src_size, uint8_t* RESTRICT dst,
1499 const size_t dst_capacity) {
1517 const uint8_t* RESTRICT src,
1518 const size_t src_size, uint8_t* RESTRICT dst,
1519 const size_t dst_capacity) {
1538 const uint8_t* RESTRICT src,
1539 const size_t src_size, uint8_t* RESTRICT dst,
1540 const size_t dst_capacity) {
1559 const uint8_t* RESTRICT src,
1560 const size_t src_size, uint8_t* RESTRICT dst,
1561 const size_t dst_capacity) {
1565#undef DECODE_GHI_BATCH_4X
1566#undef DECODE_GHI_SEQ
1567#undef DECODE_GLO_BATCH_4X
1568#undef DECODE_GLO_SEQ
1569#undef DECODE_MATCH_FAST
1571#undef DECODE_MATCH_SAFE
1594 const zxc_cctx_t* RESTRICT ctx,
const uint8_t* RESTRICT src,
const size_t src_sz,
1595 uint8_t* RESTRICT dst,
const size_t dst_cap,
const uint64_t block_index,
const int has_dict,
1599 const uint8_t type = src[0];
1600 const uint32_t comp_sz =
zxc_le32(src + 3);
1601 const int has_checksum = ctx->checksum_enabled;
1607 const size_t expected_sz =
1629 ZXC_MEMCPY(dst, data, comp_sz);
1630 decoded_sz = (int)comp_sz;
1639 if (has_checksum && LIKELY(decoded_sz >= 0)) {
1640 const uint32_t stored =
zxc_le32(data + comp_sz);
1641 if (UNLIKELY(stored !=
1657 const size_t src_sz, uint8_t* RESTRICT dst,
const size_t dst_cap,
1658 const uint64_t block_index) {
1679 const size_t src_sz, uint8_t* RESTRICT dst,
1680 const size_t dst_cap,
const uint64_t block_index) {
1702 const size_t src_sz, uint8_t* RESTRICT dst,
1703 const size_t dst_cap,
const uint64_t block_index) {
@ ZXC_ERROR_BAD_BLOCK_TYPE
Unknown or unexpected block type.
@ ZXC_ERROR_OVERFLOW
Buffer overflow detected during processing.
@ ZXC_ERROR_BAD_OFFSET
Invalid match offset during decompression.
@ ZXC_ERROR_CORRUPT_DATA
Corrupted compressed data.
@ ZXC_ERROR_BAD_HEADER
Corrupted or invalid header (checksum mismatch).
@ ZXC_ERROR_DST_TOO_SMALL
Destination buffer too small.
@ ZXC_ERROR_SRC_TOO_SMALL
Source buffer too small or truncated input.
@ ZXC_ERROR_DICT_REQUIRED
File requires a dictionary but none was provided.
@ ZXC_ERROR_BAD_CHECKSUM
A block's decoded bytes fail its checksum, or the archive digest mismatches.
@ ZXC_OK
Success (no error).
@ ZXC_ERROR_BAD_BLOCK_SIZE
Invalid block size.
#define ZXC_LIT_LEN_MASK
Mask to extract the run/literal length (lower 7 bits).
#define ZXC_ALWAYS_INLINE
Forces a function to be inlined (fallback for non-GCC/Clang/MSVC compilers).
#define ZXC_SEQ_ML_MASK
Mask to extract Match Length from a GHI sequence.
#define ZXC_CHECKSUM_RAPIDHASH
Checksum algorithm id for RapidHash (default, sole implementation).
#define ZXC_TOKEN_ML_MASK
Mask to extract Match Length from a GLO token.
#define ZXC_TOKEN_LL_MASK
Mask to extract Literal Length from a GLO token.
#define ZXC_LZ_MIN_MATCH_LEN
Minimum match length for an LZ77 match.
#define ZXC_PAD_SIZE
Safety padding appended to buffers to tolerate overruns.
#define ZXC_LZ_OFFSET_BIAS
Base bias added to encoded offsets (stored = actual - bias).
#define ZXC_GHI_HEADER_BINARY_SIZE
Binary size of a GHI block sub-header.
#define ZXC_BLOCK_HEADER_SIZE
Block header size: Type(1)+Flags(1)+Reserved(1)+Checksum(1)+CompSize(4).
#define ZXC_BLOCK_LIT_SLACK
Readable bytes a GLO/GHI payload guarantees after its literal section.
#define ZXC_GLO_MAX_INLINE_ML
Longest match a GLO sequence carries without a varint extension.
#define ZXC_NOINLINE
Prevents inlining (best-effort no-op fallback for unknown compilers).
#define ZXC_ALIGN(x)
Specifies memory alignment using C11 _Alignas.
static uint32_t zxc_read_varint(const uint8_t **ptr, const uint8_t *end)
Reads a Prefix Varint encoded integer.
#define ZXC_LIT_RLE_FLAG
Flag bit indicating an RLE run in the literal stream (0x80).
#define ZXC_BLOCK_CHECKSUM_SIZE
Size of the per-block checksum field in bytes.
#define ZXC_CACHE_LINE_SIZE
Assumed CPU cache line size for alignment.
#define ZXC_TOKEN_LIT_BITS
Bits for Literal Length in a GLO token.
#define ZXC_DECOMPRESS_TAIL_PAD
Tail padding required on the decompression destination buffer.
#define ZXC_SEQ_LL_MASK
Mask to extract Literal Length from a GHI sequence.
Compression / decompression context.
int zxc_cctx_alloc_entropy_scratch(zxc_cctx_t *ctx)
Lazily allocates the deferred decode-side entropy scratch.
int zxc_read_ghi_header(const uint8_t *src, const size_t len, zxc_gnr_header_t *gh)
Parses a GHI block header from src.
int zxc_read_glo_header_and_desc(const uint8_t *src, const size_t len, zxc_gnr_header_t *gh, uint32_t *lit_comp, uint32_t *tok_comp)
Parses a GLO block header and its section descriptors from src.
static void zxc_decode_copy_match_glo(uint8_t *d_ptr, const uint32_t off, const uint64_t ml)
GLO match copy: bounded form when the ml nibble did not saturate.
static void zxc_wild_copy32(uint8_t *dst, const uint8_t *src, const size_t len)
Copies len bytes in 32-byte wild chunks (the zxc_copy32 width).
static void zxc_decode_copy_match_short(uint8_t *d_ptr, const uint32_t off, const uint64_t ml)
Match copy for a length that cannot exceed 32 bytes.
static int zxc_ensure_entropy_scratch(const zxc_cctx_t *ctx)
Ensures the entropy decode scratch (tok_buffer + pivco_scratch) is available before decoding an entro...
static void zxc_decode_copy_match_exact(uint8_t *d_ptr, const uint8_t *match_src, const size_t off, const size_t ml)
Exact-size match copy for the tail loops (no overshoot headroom).
static void zxc_decode_copy_overlap_short(uint8_t *dst, const uint32_t off, const uint64_t ml)
Overlap copy for a run of period off (2..31) bounded by ml <= 32.
static void zxc_decode_copy_match(uint8_t *d_ptr, const uint32_t off, const uint64_t ml)
Copies an ml-byte LZ match from d_ptr-off to d_ptr, handling overlap.
static int zxc_decode_block_ghi_impl(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity, const int safe, const int has_dict)
Unified GHI (General High) block decoder body, shared by the fast, safe and dictionary variants.
#define DECODE_GLO_BATCH_4X(DECODE, ON_FAIL)
One full GLO 4x batch: token word, four offsets (1- or 2-byte form), four DECODE_GLO_SEQ emissions,...
static int zxc_decode_block_glo_entropy(const zxc_cctx_t *ctx, const uint8_t *src, size_t src_size, uint8_t *dst, size_t dst_capacity)
Cold specializations for entropy-coded GLO tokens (level 7).
static void zxc_decode_copy_overlap_run32(uint8_t *dst, const uint32_t off, const uint64_t ml)
Copies an ml-byte run of period off (2..31) with 32-byte stores.
int zxc_decompress_chunk_wrapper_dict(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_sz, uint8_t *dst, const size_t dst_cap, const uint64_t block_index)
Public dictionary chunk decoder.
static int zxc_decode_block_glo_safe(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a GLO block with the strict-tail safe loop (no wild copies).
static void zxc_decode_copy_literals(uint8_t *dst, const uint8_t *src, const uint64_t ll)
Copies ll literal bytes from src to dst using 32-byte wild copies.
static int zxc_decode_block_ghi_safe(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a GHI block with the strict-tail safe loop (no wild copies).
static int zxc_decode_block_ghi(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a no-dict GHI block (plain, inlinable path).
static int zxc_decode_block_ghi_dict(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a GHI block against a dictionary prefix (cold path).
int zxc_decompress_chunk_wrapper(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_sz, uint8_t *dst, const size_t dst_cap, const uint64_t block_index)
Public no-dict chunk decoder (decompression hot path).
static const uint8_t zxc_overlap_strides32[32]
Store stride for the 32-byte pattern: (32 / off) * off.
#define DECODE_GHI_BATCH_4X(DECODE, ON_FAIL, PREFETCH)
One full GHI 4x batch.
static int zxc_decode_block_glo_dict(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a GLO block against a dictionary prefix (cold path).
static int zxc_decode_block_glo_impl(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity, const int safe, const int has_dict, const int tok_entropy)
Unified GLO (General Low) block decoder body, shared by the fast, safe, dictionary and entropy-token ...
static void zxc_decode_fill_run(uint8_t *dst, const uint8_t byte, const uint64_t ml)
Fills an ml-byte single-byte run (LZ offset == 1) with wild stores.
int zxc_decompress_chunk_wrapper_safe(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_sz, uint8_t *dst, const size_t dst_cap, const uint64_t block_index)
Public strict-tail safe chunk decoder (dst_cap == exact decoded size).
#define GLO_OFF8
True when the GLO offset stream stores 1-byte offsets, 2-byte otherwise.
static int zxc_decompress_chunk_wrapper_body(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_sz, uint8_t *dst, const size_t dst_cap, const uint64_t block_index, const int has_dict, const int safe)
Shared chunk-decode body: validates the header, decodes, then verifies the optional checksum.
static int zxc_decode_block_glo(const zxc_cctx_t *ctx, const uint8_t *src, const size_t src_size, uint8_t *dst, const size_t dst_capacity)
Decode a no-dict GLO block (plain, inlinable path).
int zxc_huf_decode_section_dict(const uint8_t *payload, const size_t payload_size, uint8_t *dst, const size_t n, const zxc_pivco_tree_t *tree, uint8_t *scratch)
Decode a PivCo dict section against a prebuilt dict tree.
int zxc_huf_decode_section(const uint8_t *payload, const size_t payload_size, uint8_t *dst, const size_t n, uint8_t *scratch)
Decode a PivCo literal section into dst (exactly n bytes).
Internal definitions, constants, SIMD helpers, and utility functions.
#define ZXC_PIVCO_SCRATCH_PAD
Extra scratch slack required past n by the PivCo decoder.
static uint32_t zxc_le32(const void *p)
Reads a little-endian 32-bit value from a possibly unaligned address.
static void zxc_copy32(void *dst, const void *src)
Copies 32 bytes from source to destination using SIMD when available.
static uint16_t zxc_le16(const void *p)
Reads a little-endian 16-bit value from a possibly unaligned address.
static void zxc_copy16(void *dst, const void *src)
Copies exactly 16 bytes as one vector move where the ISA has one.
static uint32_t zxc_checksum(const void *input, const size_t len, const uint64_t seed, const uint8_t hash_method)
Calculates a 32-bit hash for a given input buffer.