Skip to main content

libzstd_rs_sys/lib/compress/
zstd_compress_literals.rs

1use libc::size_t;
2
3use crate::lib::common::error_private::{ERR_isError, Error};
4use crate::lib::common::huf::{
5    HUF_CElt, HUF_flags_bmi2, HUF_flags_optimalDepth, HUF_flags_preferRepeat,
6    HUF_flags_suspectUncompressible, HUF_repeat, HUF_repeat_check, HUF_repeat_none,
7    HUF_repeat_valid, HUF_OPTIMAL_DEPTH_THRESHOLD, HUF_SYMBOLVALUE_MAX,
8};
9use crate::lib::common::mem::{MEM_writeLE16, MEM_writeLE24, MEM_writeLE32};
10use crate::lib::common::zstd_internal::LitHufLog;
11use crate::lib::compress::huf_compress::{HUF_compress1X_repeat, HUF_compress4X_repeat};
12use crate::lib::compress::zstd_compress::ZSTD_hufCTables_t;
13use crate::lib::zstd::*;
14
15pub type SymbolEncodingType_e = core::ffi::c_uint;
16pub const set_repeat: SymbolEncodingType_e = 3;
17pub const set_compressed: SymbolEncodingType_e = 2;
18pub const set_rle: SymbolEncodingType_e = 1;
19pub const set_basic: SymbolEncodingType_e = 0;
20pub type huf_compress_f = Option<
21    unsafe extern "C" fn(
22        *mut core::ffi::c_void,
23        size_t,
24        *const core::ffi::c_void,
25        size_t,
26        core::ffi::c_uint,
27        core::ffi::c_uint,
28        *mut core::ffi::c_void,
29        size_t,
30        *mut HUF_CElt,
31        *mut HUF_repeat,
32        core::ffi::c_int,
33    ) -> size_t,
34>;
35#[inline]
36unsafe fn ZSTD_minGain(srcSize: size_t, strat: ZSTD_strategy) -> size_t {
37    let minlog =
38        if strat as core::ffi::c_uint >= ZSTD_btultra as core::ffi::c_int as core::ffi::c_uint {
39            strat.wrapping_sub(1)
40        } else {
41            6
42        };
43    (srcSize >> minlog).wrapping_add(2)
44}
45pub unsafe fn ZSTD_noCompressLiterals(
46    dst: *mut core::ffi::c_void,
47    dstCapacity: size_t,
48    src: *const core::ffi::c_void,
49    srcSize: size_t,
50) -> size_t {
51    let ostart = dst as *mut u8;
52    let flSize =
53        (1 + (srcSize > 31) as core::ffi::c_int + (srcSize > 4095) as core::ffi::c_int) as u32;
54    if srcSize.wrapping_add(flSize as size_t) > dstCapacity {
55        return Error::dstSize_tooSmall.to_error_code();
56    }
57    match flSize {
58        1 => {
59            *ostart.offset(0) =
60                (set_basic as core::ffi::c_int as u32 as size_t).wrapping_add(srcSize << 3) as u8;
61        }
62        2 => {
63            MEM_writeLE16(
64                ostart as *mut core::ffi::c_void,
65                ((set_basic as core::ffi::c_int as u32).wrapping_add(((1) << 2) as u32) as size_t)
66                    .wrapping_add(srcSize << 4) as u16,
67            );
68        }
69        3 => {
70            MEM_writeLE32(
71                ostart as *mut core::ffi::c_void,
72                ((set_basic as core::ffi::c_int as u32).wrapping_add(((3) << 2) as u32) as size_t)
73                    .wrapping_add(srcSize << 4) as u32,
74            );
75        }
76        _ => {}
77    }
78    libc::memcpy(
79        ostart.offset(flSize as isize) as *mut core::ffi::c_void,
80        src,
81        srcSize as libc::size_t,
82    );
83    srcSize.wrapping_add(flSize as size_t)
84}
85unsafe fn allBytesIdentical(src: *const core::ffi::c_void, srcSize: size_t) -> core::ffi::c_int {
86    let b = *(src as *const u8).offset(0);
87    let mut p: size_t = 0;
88    p = 1;
89    while p < srcSize {
90        if *(src as *const u8).add(p) as core::ffi::c_int != b as core::ffi::c_int {
91            return 0;
92        }
93        p = p.wrapping_add(1);
94    }
95    1
96}
97pub unsafe fn ZSTD_compressRleLiteralsBlock(
98    dst: *mut core::ffi::c_void,
99    dstCapacity: size_t,
100    src: *const core::ffi::c_void,
101    srcSize: size_t,
102) -> size_t {
103    let ostart = dst as *mut u8;
104    let flSize =
105        (1 + (srcSize > 31) as core::ffi::c_int + (srcSize > 4095) as core::ffi::c_int) as u32;
106    match flSize {
107        1 => {
108            *ostart.offset(0) =
109                (set_rle as core::ffi::c_int as u32 as size_t).wrapping_add(srcSize << 3) as u8;
110        }
111        2 => {
112            MEM_writeLE16(
113                ostart as *mut core::ffi::c_void,
114                ((set_rle as core::ffi::c_int as u32).wrapping_add(((1) << 2) as u32) as size_t)
115                    .wrapping_add(srcSize << 4) as u16,
116            );
117        }
118        3 => {
119            MEM_writeLE32(
120                ostart as *mut core::ffi::c_void,
121                ((set_rle as core::ffi::c_int as u32).wrapping_add(((3) << 2) as u32) as size_t)
122                    .wrapping_add(srcSize << 4) as u32,
123            );
124        }
125        _ => {}
126    }
127    *ostart.offset(flSize as isize) = *(src as *const u8);
128    flSize.wrapping_add(1) as size_t
129}
130unsafe fn ZSTD_minLiteralsToCompress(strategy: ZSTD_strategy, huf_repeat: HUF_repeat) -> size_t {
131    let shift = if (9 - strategy as core::ffi::c_int) < 3 {
132        9 - strategy as core::ffi::c_int
133    } else {
134        3
135    };
136
137    if huf_repeat as core::ffi::c_uint == HUF_repeat_valid as core::ffi::c_int as core::ffi::c_uint
138    {
139        6
140    } else {
141        (8) << shift
142    }
143}
144pub unsafe fn ZSTD_compressLiterals(
145    dst: *mut core::ffi::c_void,
146    dstCapacity: size_t,
147    src: *const core::ffi::c_void,
148    srcSize: size_t,
149    entropyWorkspace: *mut core::ffi::c_void,
150    entropyWorkspaceSize: size_t,
151    prevHuf: *const ZSTD_hufCTables_t,
152    nextHuf: *mut ZSTD_hufCTables_t,
153    strategy: ZSTD_strategy,
154    disableLiteralCompression: core::ffi::c_int,
155    suspectUncompressible: core::ffi::c_int,
156    bmi2: core::ffi::c_int,
157) -> size_t {
158    let lhSize = (3
159        + (srcSize >= ((1) << 10) as size_t) as core::ffi::c_int
160        + (srcSize >= (16 * ((1) << 10)) as size_t) as core::ffi::c_int) as size_t;
161    let ostart = dst as *mut u8;
162    let mut singleStream = (srcSize < 256) as core::ffi::c_int as u32;
163    let mut hType = set_compressed;
164    let mut cLitSize: size_t = 0;
165    libc::memcpy(
166        nextHuf as *mut core::ffi::c_void,
167        prevHuf as *const core::ffi::c_void,
168        ::core::mem::size_of::<ZSTD_hufCTables_t>() as core::ffi::c_ulong as libc::size_t,
169    );
170    if disableLiteralCompression != 0 {
171        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
172    }
173    if srcSize < ZSTD_minLiteralsToCompress(strategy, (*prevHuf).repeatMode) {
174        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
175    }
176    if dstCapacity < lhSize.wrapping_add(1) {
177        return Error::dstSize_tooSmall.to_error_code();
178    }
179    let mut repeat = (*prevHuf).repeatMode;
180    let flags =
181        (if bmi2 != 0 {
182            HUF_flags_bmi2 as core::ffi::c_int
183        } else {
184            0
185        }) | (if (strategy as core::ffi::c_uint)
186            < ZSTD_lazy as core::ffi::c_int as core::ffi::c_uint
187            && srcSize <= 1024
188        {
189            HUF_flags_preferRepeat as core::ffi::c_int
190        } else {
191            0
192        }) | (if strategy as core::ffi::c_uint >= HUF_OPTIMAL_DEPTH_THRESHOLD as core::ffi::c_uint {
193            HUF_flags_optimalDepth as core::ffi::c_int
194        } else {
195            0
196        }) | (if suspectUncompressible != 0 {
197            HUF_flags_suspectUncompressible as core::ffi::c_int
198        } else {
199            0
200        });
201    let mut huf_compress: huf_compress_f = None;
202    if repeat as core::ffi::c_uint == HUF_repeat_valid as core::ffi::c_int as core::ffi::c_uint
203        && lhSize == 3
204    {
205        singleStream = 1;
206    }
207    huf_compress = if singleStream != 0 {
208        Some(
209            HUF_compress1X_repeat
210                as unsafe extern "C" fn(
211                    *mut core::ffi::c_void,
212                    size_t,
213                    *const core::ffi::c_void,
214                    size_t,
215                    core::ffi::c_uint,
216                    core::ffi::c_uint,
217                    *mut core::ffi::c_void,
218                    size_t,
219                    *mut HUF_CElt,
220                    *mut HUF_repeat,
221                    core::ffi::c_int,
222                ) -> size_t,
223        )
224    } else {
225        Some(
226            HUF_compress4X_repeat
227                as unsafe extern "C" fn(
228                    *mut core::ffi::c_void,
229                    size_t,
230                    *const core::ffi::c_void,
231                    size_t,
232                    core::ffi::c_uint,
233                    core::ffi::c_uint,
234                    *mut core::ffi::c_void,
235                    size_t,
236                    *mut HUF_CElt,
237                    *mut HUF_repeat,
238                    core::ffi::c_int,
239                ) -> size_t,
240        )
241    };
242    cLitSize = huf_compress.unwrap_unchecked()(
243        ostart.add(lhSize) as *mut core::ffi::c_void,
244        dstCapacity.wrapping_sub(lhSize),
245        src,
246        srcSize,
247        HUF_SYMBOLVALUE_MAX as core::ffi::c_uint,
248        LitHufLog as core::ffi::c_uint,
249        entropyWorkspace,
250        entropyWorkspaceSize,
251        ((*nextHuf).CTable).as_mut_ptr(),
252        &mut repeat,
253        flags,
254    );
255    if repeat as core::ffi::c_uint != HUF_repeat_none as core::ffi::c_int as core::ffi::c_uint {
256        hType = set_repeat;
257    }
258    let minGain = ZSTD_minGain(srcSize, strategy);
259    if cLitSize == 0 || cLitSize >= srcSize.wrapping_sub(minGain) || ERR_isError(cLitSize) {
260        libc::memcpy(
261            nextHuf as *mut core::ffi::c_void,
262            prevHuf as *const core::ffi::c_void,
263            ::core::mem::size_of::<ZSTD_hufCTables_t>() as core::ffi::c_ulong as libc::size_t,
264        );
265        return ZSTD_noCompressLiterals(dst, dstCapacity, src, srcSize);
266    }
267    if cLitSize == 1 && (srcSize >= 8 || allBytesIdentical(src, srcSize) != 0) {
268        libc::memcpy(
269            nextHuf as *mut core::ffi::c_void,
270            prevHuf as *const core::ffi::c_void,
271            ::core::mem::size_of::<ZSTD_hufCTables_t>() as core::ffi::c_ulong as libc::size_t,
272        );
273        return ZSTD_compressRleLiteralsBlock(dst, dstCapacity, src, srcSize);
274    }
275    if hType as core::ffi::c_uint == set_compressed as core::ffi::c_int as core::ffi::c_uint {
276        (*nextHuf).repeatMode = HUF_repeat_check;
277    }
278    match lhSize {
279        3 => {
280            singleStream == 0;
281            let lhc = (hType as core::ffi::c_uint)
282                .wrapping_add(((singleStream == 0) as core::ffi::c_int as u32) << 2)
283                .wrapping_add((srcSize as u32) << 4)
284                .wrapping_add((cLitSize as u32) << 14);
285            MEM_writeLE24(ostart as *mut core::ffi::c_void, lhc);
286        }
287        4 => {
288            let lhc_0 = (hType as core::ffi::c_uint)
289                .wrapping_add(((2) << 2) as core::ffi::c_uint)
290                .wrapping_add((srcSize as u32) << 4)
291                .wrapping_add((cLitSize as u32) << 18);
292            MEM_writeLE32(ostart as *mut core::ffi::c_void, lhc_0);
293        }
294        5 => {
295            let lhc_1 = (hType as core::ffi::c_uint)
296                .wrapping_add(((3) << 2) as core::ffi::c_uint)
297                .wrapping_add((srcSize as u32) << 4)
298                .wrapping_add((cLitSize as u32) << 22);
299            MEM_writeLE32(ostart as *mut core::ffi::c_void, lhc_1);
300            *ostart.offset(4) = (cLitSize >> 10) as u8;
301        }
302        _ => {}
303    }
304    lhSize.wrapping_add(cLitSize)
305}