use crate::{AUX_NONE, CODE_CONT, build_block, contr_len};
pub(crate) const LUT: [u8; 64] = {
let mut t = [2u8; 64]; t[0x00] = 0;
t[0x10] = 0;
t[0x20] = 0;
t[0x30] = 0; t[0x01] = 1;
t[0x02] = 1;
t[0x31] = 1; t[0x03] = 3; t[0x04] = 4; t[0x05] = 5; t[0x3A] = 2; t[0x09] = 6; t[0x0F] = CODE_CONT;
t
};
streams!(
Cls { lead, cont, l, n, other, nl, sp, ws, apo }
);
pub(crate) fn cls(text: &[u8], tags: &[u8], base: usize, len: usize, code: u8) -> (Cls, u8) {
let valid = if len == 64 { !0u64 } else { (1u64 << len) - 1 };
let (b, last_code) =
build_block::<{ AUX_NONE }, false>(text, tags, base, len, &LUT, code, false);
let (p0, p1, p2) = (b.p0, b.p1, b.p2);
let a = !p2 & !p1;
let nl = !p2 & p1 & p0;
let c = Cls {
lead: valid & !b.cont,
cont: b.cont,
l: a & !p0 & valid,
n: a & p0,
other: p1 & !p0 & valid, nl,
sp: p2 & !p1 & !p0,
ws: (p2 & !p1) | nl, apo: p2 & p1 & !p0,
};
(c, last_code)
}
pub(crate) fn contractions(
text: &[u8],
st: u64,
apo: u64,
base: usize,
ntext: usize,
ci: bool,
carry: &mut (u64, u64),
) -> (u64, u64) {
let (mut opens, mut inner) = *carry;
*carry = (0, 0);
let mut a = st & apo;
while a != 0 {
let j = a.trailing_zeros() as usize;
a &= a - 1;
let p = base + j;
let k = contr_len(text, p, ci);
if k == 0 {
continue;
}
let hi = j + k; if j + 1 < 64 {
let up = if hi >= 64 { !0u64 } else { (1u64 << hi) - 1 };
inner |= up & !((1u64 << (j + 1)) - 1);
}
if hi > 64 {
carry.1 |= (1u64 << (hi - 64)) - 1;
}
if p + k < ntext {
if hi < 64 {
opens |= 1u64 << hi;
} else {
carry.0 |= 1u64 << (hi - 64);
}
}
}
(opens, inner)
}