static really_inline
hwlm_error_t checkMatched(const struct noodTable *n, const u8 *buf, size_t len,
const struct cb_info *cbi, const u8 *d,
svbool_t matched, bool needsConfirm) {
assert(d >= buf);
size_t basePos = d - buf;
svbool_t next_match = svpnext_b8(matched, svpfalse());
do {
svbool_t brk = svbrkb_z(svptrue_b8(), next_match);
size_t matchPos = basePos + svcntp_b8(svptrue_b8(), brk);
DEBUG_PRINTF("match pos %zu\n", matchPos);
assert(matchPos < len);
hwlmcb_rv_t rv = final(n, buf, len, needsConfirm, cbi, matchPos);
RETURN_IF_TERMINATED(rv);
next_match = svpnext_b8(matched, next_match);
} while (unlikely(svptest_any(svptrue_b8(), next_match)));
return HWLM_SUCCESS;
}
static really_inline
hwlm_error_t singleCheckMatched(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
const u8 *d, svbool_t matched) {
if (unlikely(svptest_any(svptrue_b8(), matched))) {
hwlm_error_t rv = checkMatched(n, buf, len, cbi, d, matched,
n->msk_len != 1);
RETURN_IF_TERMINATED(rv);
}
return HWLM_SUCCESS;
}
static really_inline
svbool_t singleMatched(svuint8_t chars, const u8 *d, svbool_t pg) {
return svmatch(pg, svld1_u8(pg, d), chars);
}
static really_inline
hwlm_error_t scanSingleOnce(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
svuint8_t chars, const u8 *d, const u8 *e) {
DEBUG_PRINTF("start %p end %p\n", d, e);
assert(d < e);
assert(d >= buf);
DEBUG_PRINTF("l = %td\n", e - d);
svbool_t pg = svwhilelt_b8_s64(0, e - d);
svbool_t matched = singleMatched(chars, d, pg);
return singleCheckMatched(n, buf, len, cbi, d, matched);
}
static really_inline
hwlm_error_t scanSingleLoop(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
svuint8_t chars, const u8 *d, const u8 *e) {
assert(d < e);
assert(d >= buf);
size_t loops = (e - d) / svcntb();
DEBUG_PRINTF("loops %zu \n", loops);
assert(d + (loops * svcntb()) <= e);
for (size_t i = 0; i < loops; i++, d += svcntb()) {
DEBUG_PRINTF("d %p \n", d);
svbool_t matched = singleMatched(chars, d, svptrue_b8());
hwlm_error_t rv = singleCheckMatched(n, buf, len, cbi, d, matched);
RETURN_IF_TERMINATED(rv);
}
DEBUG_PRINTF("d %p e %p \n", d, e);
return d == e ? HWLM_SUCCESS
: scanSingleOnce(n, buf, len, cbi, chars, d, e);
}
static really_inline
hwlm_error_t scanSingle(const struct noodTable *n, const u8 *buf, size_t len,
size_t offset, bool noCase, const struct cb_info *cbi) {
if (!ourisalpha(n->key0)) {
noCase = false; }
size_t start = offset + n->msk_len - 1;
const u8 *d = buf + start;
const u8 *e = buf + len;
DEBUG_PRINTF("start %p end %p \n", d, e);
assert(d < e);
assert(d >= buf);
svuint8_t chars = getCharMaskSingle(n->key0, noCase);
size_t scan_len = e - d;
if (scan_len <= svcntb()) {
return scanSingleOnce(n, buf, len, cbi, chars, d, e);
}
const u8 *d1 = ROUNDUP_PTR(d, svcntb_pat(SV_POW2));
if (d != d1) {
DEBUG_PRINTF("until aligned %p \n", d1);
hwlm_error_t rv = scanSingleOnce(n, buf, len, cbi, chars, d, d1);
RETURN_IF_TERMINATED(rv);
}
return scanSingleLoop(n, buf, len, cbi, chars, d1, e);
}
static really_inline
hwlm_error_t doubleCheckMatched(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
const u8 *d, svbool_t matched,
svbool_t matched_rot, svbool_t any) {
if (unlikely(svptest_any(svptrue_b8(), any))) {
svuint8_t matched_vec = svdup_u8_z(matched, 1);
matched = svcmpeq_n_u8(svptrue_b8(), svinsr_n_u8(matched_vec, 0), 1);
matched = svorr_z(svptrue_b8(), matched, matched_rot);
assert(d > buf);
hwlm_error_t rv = checkMatched(n, buf, len, cbi, d - 1, matched,
n->msk_len != 2);
RETURN_IF_TERMINATED(rv);
}
return HWLM_SUCCESS;
}
static really_inline
svbool_t doubleMatchedLoop(svuint16_t chars, const u8 *d,
svbool_t * const matched, svbool_t * const matched_rot) {
svuint16_t vec = svreinterpret_u16(svld1_u8(svptrue_b8(), d));
svuint16_t vec_rot = svreinterpret_u16(svld1_u8(svptrue_b8(), d - 1));
*matched = svmatch(svptrue_b8(), vec, chars);
*matched_rot = svmatch(svptrue_b8(), vec_rot, chars);
return svorr_z(svptrue_b8(), *matched, *matched_rot);
}
static really_inline
hwlm_error_t scanDoubleOnce(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
svuint8_t chars, const u8 *d, const u8 *e) {
DEBUG_PRINTF("start %p end %p\n", d, e);
assert(d < e);
assert(d > buf);
const ptrdiff_t size = e - d;
svbool_t pg = svwhilelt_b8_s64(0, size);
svbool_t pg_rot = svwhilelt_b8_s64(0, size + 1);
svuint16_t vec = svreinterpret_u16(svld1_u8(pg, d));
svuint16_t vec_rot = svreinterpret_u16(svld1_u8(pg_rot, d - 1));
if (unlikely(n->key1 == '\0')) {
if (size % 2) {
svbool_t lane_to_disable = svrev_b8(svpfirst(svrev_b8(pg), svpfalse()));
pg = sveor_z(svptrue_b8(), pg, lane_to_disable);
} else {
pg_rot = pg;
}
}
svbool_t matched = svmatch(pg, vec, svreinterpret_u16(chars));
svbool_t matched_rot = svmatch(pg_rot, vec_rot, svreinterpret_u16(chars));
svbool_t any = svorr_z(svptrue_b8(), matched, matched_rot);
return doubleCheckMatched(n, buf, len, cbi, d, matched, matched_rot, any);
}
static really_inline
hwlm_error_t scanDoubleLoop(const struct noodTable *n, const u8 *buf,
size_t len, const struct cb_info *cbi,
svuint8_t chars, const u8 *d, const u8 *e) {
assert(d < e);
assert(d > buf);
size_t loops = (e - d) / svcntb();
DEBUG_PRINTF("loops %zu \n", loops);
assert(d + (loops * svcntb()) <= e);
for (size_t i = 0; i < loops; i++, d += svcntb()) {
DEBUG_PRINTF("d %p \n", d);
svbool_t matched, matched_rot;
svbool_t any = doubleMatchedLoop(svreinterpret_u16(chars), d, &matched, &matched_rot);
hwlm_error_t rv = doubleCheckMatched(n, buf, len, cbi, d,
matched, matched_rot, any);
RETURN_IF_TERMINATED(rv);
}
DEBUG_PRINTF("d %p e %p \n", d, e);
return d == e ? HWLM_SUCCESS
: scanDoubleOnce(n, buf, len, cbi, chars, d, e);
}
static really_inline
hwlm_error_t scanDouble(const struct noodTable *n, const u8 *buf, size_t len,
size_t offset, bool noCase, const struct cb_info *cbi) {
size_t end = len - n->key_offset + 2;
size_t start = offset + n->msk_len - n->key_offset;
const u8 *d = buf + start;
const u8 *e = buf + end;
DEBUG_PRINTF("start %p end %p \n", d, e);
assert(d < e);
assert(d >= buf);
size_t scan_len = e - d;
if (scan_len < 2) {
return HWLM_SUCCESS;
}
++d;
svuint8_t chars = svreinterpret_u8(getCharMaskDouble(n->key0, n->key1, noCase));
if ((size_t)(e - d) <= svcntb()) {
return scanDoubleOnce(n, buf, len, cbi, chars, d, e);
}
const u8 *d1 = ROUNDUP_PTR(d, svcntb_pat(SV_POW2));
if (d != d1) {
DEBUG_PRINTF("until aligned %p \n", d1);
hwlm_error_t rv = scanDoubleOnce(n, buf, len, cbi, chars,
d, d1);
RETURN_IF_TERMINATED(rv);
}
return scanDoubleLoop(n, buf, len, cbi, chars, d1, e);
}