static really_inline void pureLiteralStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) { assert(stream_state); assert(scratch); char *state = getMultiState(stream_state); u8 broken = getBroken(state); if (unlikely(broken)) { assert(broken == BROKEN_FROM_USER || broken == BROKEN_EXHAUSTED); scratch->core_info.broken = broken; return; } const struct RoseEngine *rose = stream_state->rose; const struct HWLM *ftable = getFLiteralMatcher(rose); size_t len2 = scratch->core_info.len; u8 *hwlm_stream_state; if (rose->floatingStreamState) { hwlm_stream_state = getFloatingMatcherState(rose, (u8 *)state); } else { hwlm_stream_state = NULL; } DEBUG_PRINTF("::: streaming rose ::: offset = %llu len = %zu\n", stream_state->offset, scratch->core_info.len); // Pure literal cases don't have floatingMinDistance set, so we always // start the match region at zero. const size_t start = 0; hwlmExecStreaming(ftable, scratch, len2, start, selectHwlmAdaptor(rose), scratch, rose->initialGroups, hwlm_stream_state); if (!told_to_stop_matching(scratch) && isAllExhausted(rose, scratch->core_info.exhaustionVector)) { DEBUG_PRINTF("stream exhausted\n"); scratch->core_info.broken = BROKEN_EXHAUSTED; } }
static really_inline void pureLiteralStreamExec(struct hs_stream *stream_state, struct hs_scratch *scratch) { assert(stream_state); assert(scratch); assert(!can_stop_matching(scratch)); char *state = getMultiState(stream_state); const struct RoseEngine *rose = stream_state->rose; const struct HWLM *ftable = getFLiteralMatcher(rose); size_t len2 = scratch->core_info.len; u8 *hwlm_stream_state; if (rose->floatingStreamState) { hwlm_stream_state = getFloatingMatcherState(rose, state); } else { hwlm_stream_state = NULL; } DEBUG_PRINTF("::: streaming rose ::: offset = %llu len = %zu\n", stream_state->offset, scratch->core_info.len); // Pure literal cases don't have floatingMinDistance set, so we always // start the match region at zero. const size_t start = 0; hwlmExecStreaming(ftable, scratch, len2, start, rosePureLiteralCallback, scratch, rose->initialGroups, hwlm_stream_state); if (!told_to_stop_matching(scratch) && isAllExhausted(rose, scratch->core_info.exhaustionVector)) { DEBUG_PRINTF("stream exhausted\n"); scratch->core_info.status |= STATUS_EXHAUSTED; } }
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; }