static rose_inline hwlmcb_rv_t roseEodRunMatcher(const struct RoseEngine *t, u64a offset, struct hs_scratch *scratch, const char is_streaming) { assert(t->ematcherOffset); size_t eod_len; const u8 *eod_data; if (!is_streaming) { /* Block */ eod_data = scratch->core_info.buf; eod_len = scratch->core_info.len; } else { /* Streaming */ eod_len = scratch->core_info.hlen; eod_data = scratch->core_info.hbuf; } assert(eod_data); assert(eod_len); // If we don't have enough bytes to produce a match from an EOD table scan, // there's no point scanning. if (eod_len < t->eodmatcherMinWidth) { DEBUG_PRINTF("len=%zu < eodmatcherMinWidth=%u\n", eod_len, t->eodmatcherMinWidth); return MO_CONTINUE_MATCHING; } // Ensure that we only need scan the last N bytes, where N is the length of // the eod-anchored matcher region. size_t adj = eod_len - MIN(eod_len, t->ematcherRegionSize); DEBUG_PRINTF("eod offset=%llu, eod length=%zu\n", offset, eod_len); struct RoseContext *tctxt = &scratch->tctxt; /* update side_curr for eod_len */ tctxt->side_curr = offset - eod_len; /* no need to enable any sidecar groups as they are for .*A.* constructs * not allowed in the eod table */ const struct HWLM *etable = getELiteralMatcher(t); hwlmExec(etable, eod_data, eod_len, adj, roseCallback, tctxt, tctxt->groups); // We may need to fire delayed matches u8 dummy_delay_mask = 0; return cleanUpDelayed(0, offset, tctxt, &dummy_delay_mask); }
void roseStreamExec(const struct RoseEngine *t, struct hs_scratch *scratch) { DEBUG_PRINTF("OH HAI [%llu, %llu)\n", scratch->core_info.buf_offset, scratch->core_info.buf_offset + (u64a)scratch->core_info.len); assert(t); assert(scratch->core_info.hbuf); assert(scratch->core_info.buf); // We should not have been called if we've already been told to terminate // matching. assert(!told_to_stop_matching(scratch)); assert(mmbit_sparse_iter_state_size(t->rolesWithStateCount) < MAX_SPARSE_ITER_STATES); size_t length = scratch->core_info.len; u64a offset = scratch->core_info.buf_offset; // We may have a maximum width (for engines constructed entirely // of bi-anchored patterns). If this write would result in us progressing // beyond this point, we cannot possibly match. if (t->maxBiAnchoredWidth != ROSE_BOUND_INF && offset + length > t->maxBiAnchoredWidth) { DEBUG_PRINTF("bailing, write would progress beyond maxBAWidth\n"); return; } char *state = scratch->core_info.state; struct RoseContext *tctxt = &scratch->tctxt; tctxt->mpv_inactive = 0; tctxt->groups = loadGroups(t, state); tctxt->lit_offset_adjust = offset + 1; // index after last byte tctxt->delayLastEndOffset = offset; tctxt->lastEndOffset = offset; tctxt->filledDelayedSlots = 0; tctxt->lastMatchOffset = 0; tctxt->minMatchOffset = offset; tctxt->minNonMpvMatchOffset = offset; tctxt->next_mpv_offset = 0; DEBUG_PRINTF("BEGIN: history len=%zu, buffer len=%zu groups=%016llx\n", scratch->core_info.hlen, scratch->core_info.len, tctxt->groups); fatbit_clear(scratch->aqa); scratch->al_log_sum = 0; scratch->catchup_pq.qm_size = 0; if (t->outfixBeginQueue != t->outfixEndQueue) { streamInitSufPQ(t, state, scratch); } runEagerPrefixesStream(t, scratch); u32 alen = t->anchoredDistance > offset ? MIN(length + offset, t->anchoredDistance) - offset : 0; const struct anchored_matcher_info *atable = getALiteralMatcher(t); if (atable && alen) { DEBUG_PRINTF("BEGIN ANCHORED %zu/%u\n", scratch->core_info.hlen, alen); runAnchoredTableStream(t, atable, alen, offset, scratch); if (can_stop_matching(scratch)) { goto exit; } } const struct HWLM *ftable = getFLiteralMatcher(t); if (ftable) { if (t->noFloatingRoots && !roseHasInFlightMatches(t, state, scratch)) { DEBUG_PRINTF("skip FLOATING: no inflight matches\n"); goto flush_delay_and_exit; } size_t flen = length; if (t->floatingDistance != ROSE_BOUND_INF) { flen = t->floatingDistance > offset ? MIN(t->floatingDistance, length + offset) - offset : 0; } size_t hlength = scratch->core_info.hlen; char rebuild = hlength && (scratch->core_info.status & STATUS_DELAY_DIRTY) && (t->maxFloatingDelayedMatch == ROSE_BOUND_INF || offset < t->maxFloatingDelayedMatch); DEBUG_PRINTF("**rebuild %hhd status %hhu mfdm %u, offset %llu\n", rebuild, scratch->core_info.status, t->maxFloatingDelayedMatch, offset); if (!flen) { if (rebuild) { /* rebuild floating delayed match stuff */ do_rebuild(t, ftable, scratch); } goto flush_delay_and_exit; } if (rebuild) { /* rebuild floating delayed match stuff */ do_rebuild(t, ftable, scratch); } if (flen + offset <= t->floatingMinDistance) { DEBUG_PRINTF("skip FLOATING: before floating min\n"); goto flush_delay_and_exit; } size_t start = 0; if (offset < t->floatingMinDistance) { // This scan crosses the floating min distance, so we can use that // to set HWLM's "start" offset. start = t->floatingMinDistance - offset; } DEBUG_PRINTF("start=%zu\n", start); u8 *stream_state; if (t->floatingStreamState) { stream_state = getFloatingMatcherState(t, state); } else { stream_state = NULL; } DEBUG_PRINTF("BEGIN FLOATING (over %zu/%zu)\n", flen, length); hwlmExecStreaming(ftable, scratch, flen, start, roseFloatingCallback, scratch, tctxt->groups & t->floating_group_mask, stream_state); } flush_delay_and_exit: DEBUG_PRINTF("flushing floating\n"); if (cleanUpDelayed(t, scratch, length, offset) == HWLM_TERMINATE_MATCHING) { return; } exit: DEBUG_PRINTF("CLEAN UP TIME\n"); if (!can_stop_matching(scratch)) { ensureStreamNeatAndTidy(t, state, scratch, length, offset); } DEBUG_PRINTF("DONE STREAMING SCAN, status = %u\n", scratch->core_info.status); return; }