static never_inline void soleOutfixBlockExec(const struct RoseEngine *t, struct hs_scratch *scratch) { assert(t); assert(scratch); initSomState(t, (u8 *)scratch->core_info.state); assert(t->outfixEndQueue == 1); assert(!t->amatcherOffset); assert(!t->ematcherOffset); assert(!t->fmatcherOffset); const struct NFA *nfa = getNfaByQueue(t, 0); size_t len = nfaRevAccelCheck(nfa, scratch->core_info.buf, scratch->core_info.len); if (!len) { return; } struct mq *q = scratch->queues; initQueue(q, 0, t, scratch); q->length = len; /* adjust for rev_accel */ nfaQueueInitState(nfa, q); pushQueueAt(q, 0, MQE_START, 0); pushQueueAt(q, 1, MQE_TOP, 0); pushQueueAt(q, 2, MQE_END, scratch->core_info.len); char rv = nfaQueueExec(q->nfa, q, scratch->core_info.len); if (rv && nfaAcceptsEod(nfa) && len == scratch->core_info.len) { nfaCheckFinalState(nfa, q->state, q->streamState, q->length, q->cb, q->som_cb, scratch); } }
static never_inline void soleOutfixEodExec(hs_stream_t *id, hs_scratch_t *scratch) { const struct RoseEngine *t = id->rose; if (can_stop_matching(scratch)) { DEBUG_PRINTF("stream already broken\n"); return; } if (isAllExhausted(t, scratch->core_info.exhaustionVector)) { DEBUG_PRINTF("stream exhausted\n"); return; } assert(t->outfixEndQueue == 1); assert(!t->amatcherOffset); assert(!t->ematcherOffset); assert(!t->fmatcherOffset); const struct NFA *nfa = getNfaByQueue(t, 0); struct mq *q = scratch->queues; initOutfixQueue(q, 0, t, scratch); if (!scratch->core_info.buf_offset) { DEBUG_PRINTF("buf_offset is zero\n"); return; /* no vacuous engines */ } nfaExpandState(nfa, q->state, q->streamState, q->offset, queue_prev_byte(q, 0)); assert(nfaAcceptsEod(nfa)); nfaCheckFinalState(nfa, q->state, q->streamState, q->offset, q->cb, q->som_cb, scratch); }
char nfaExecTamarama0_testEOD(const struct NFA *n, const char *state, const char *streamState, u64a offset, NfaCallback callback, void *context) { const struct Tamarama *t = getImplNfa(n); u32 activeIdx = loadActiveIdx(streamState, t->activeIdxSize); if (activeIdx == t->numSubEngines) { return MO_CONTINUE_MATCHING; } const struct NFA *sub = getSubEngine(t, activeIdx); if (nfaAcceptsEod(sub)) { assert(!isContainerType(sub->type)); const char *subStreamState = streamState + t->activeIdxSize; return nfaCheckFinalState(sub, state, subStreamState, offset, callback, context); } return MO_CONTINUE_MATCHING; }
static rose_inline void roseCheckNfaEod(const struct RoseEngine *t, u8 *state, struct hs_scratch *scratch, u64a offset, const char is_streaming) { /* data, len is used for state decompress, should be full available data */ const u8 *aa = getActiveLeafArray(t, state); const u32 aaCount = t->activeArrayCount; u8 key = 0; if (is_streaming) { const u8 *eod_data = scratch->core_info.hbuf; size_t eod_len = scratch->core_info.hlen; key = eod_len ? eod_data[eod_len - 1] : 0; } for (u32 qi = mmbit_iterate(aa, aaCount, MMB_INVALID); qi != MMB_INVALID; qi = mmbit_iterate(aa, aaCount, qi)) { const struct NfaInfo *info = getNfaInfoByQueue(t, qi); const struct NFA *nfa = getNfaByInfo(t, info); if (!nfaAcceptsEod(nfa)) { DEBUG_PRINTF("nfa %u does not accept eod\n", qi); continue; } DEBUG_PRINTF("checking nfa %u\n", qi); char *fstate = scratch->fullState + info->fullStateOffset; const char *sstate = (const char *)state + info->stateOffset; if (is_streaming) { // Decompress stream state. nfaExpandState(nfa, fstate, sstate, offset, key); } nfaCheckFinalState(nfa, fstate, sstate, offset, scratch->tctxt.cb, scratch->tctxt.cb_som, scratch->tctxt.userCtx); } }
static rose_inline void roseCheckEodSuffixes(const struct RoseEngine *t, u8 *state, u64a offset, struct hs_scratch *scratch) { const u8 *aa = getActiveLeafArray(t, state); const u32 aaCount = t->activeArrayCount; UNUSED u32 qCount = t->queueCount; for (u32 qi = mmbit_iterate(aa, aaCount, MMB_INVALID); qi != MMB_INVALID; qi = mmbit_iterate(aa, aaCount, qi)) { const struct NfaInfo *info = getNfaInfoByQueue(t, qi); const struct NFA *nfa = getNfaByInfo(t, info); assert(nfaAcceptsEod(nfa)); DEBUG_PRINTF("checking nfa %u\n", qi); assert(fatbit_isset(scratch->aqa, qCount, qi)); /* we have just been triggered */ char *fstate = scratch->fullState + info->fullStateOffset; const char *sstate = (const char *)state + info->stateOffset; struct mq *q = scratch->queues + qi; pushQueueNoMerge(q, MQE_END, scratch->core_info.len); q->context = NULL; /* rose exec is used as we don't want to / can't raise matches in the * history buffer. */ char rv = nfaQueueExecRose(q->nfa, q, MO_INVALID_IDX); if (rv) { /* nfa is still alive */ nfaCheckFinalState(nfa, fstate, sstate, offset, scratch->tctxt.cb, scratch->tctxt.cb_som, scratch->tctxt.userCtx); } } }