Exemplo n.º 1
0
template <class LbrStruct> static
void fillNfa(NFA *nfa, lbr_common *c, ReportID report, const depth &repeatMin,
             const depth &repeatMax, u32 minPeriod, enum RepeatType rtype) {
    assert(nfa);

    RepeatStateInfo rsi(rtype, repeatMin, repeatMax, minPeriod);

    DEBUG_PRINTF("selected %s model for {%s,%s} repeat\n",
                 repeatTypeName(rtype), repeatMin.str().c_str(),
                 repeatMax.str().c_str());

    // Fill the lbr_common structure first. Note that the RepeatInfo structure
    // directly follows the LbrStruct.
    const u32 info_offset = sizeof(LbrStruct);
    c->repeatInfoOffset = info_offset;
    c->report = report;

    RepeatInfo *info = (RepeatInfo *)((char *)c + info_offset);
    info->type = verify_u8(rtype);
    info->repeatMin = depth_to_u32(repeatMin);
    info->repeatMax = depth_to_u32(repeatMax);
    info->stateSize = rsi.stateSize;
    info->packedCtrlSize = rsi.packedCtrlSize;
    info->horizon = rsi.horizon;
    info->minPeriod = minPeriod;
    copy_bytes(&info->packedFieldSizes, rsi.packedFieldSizes);
    info->patchCount = rsi.patchCount;
    info->patchSize = rsi.patchSize;
    info->encodingSize = rsi.encodingSize;
    info->patchesOffset = rsi.patchesOffset;

    // Fill the NFA structure.
    nfa->nPositions = repeatMin;
    nfa->streamStateSize = verify_u32(rsi.packedCtrlSize + rsi.stateSize);
    nfa->scratchStateSize = (u32)sizeof(lbr_state);
    nfa->minWidth = verify_u32(repeatMin);
    nfa->maxWidth = repeatMax.is_finite() ? verify_u32(repeatMax) : 0;

    // Fill the lbr table for sparse lbr model.
    if (rtype == REPEAT_SPARSE_OPTIMAL_P) {
        u64a *table = getTable<LbrStruct>(nfa);
        // Adjust table length according to the optimal patch length.
        size_t len = nfa->length;
        assert((u32)repeatMax >= rsi.patchSize);
        len -= sizeof(u64a) * ((u32)repeatMax - rsi.patchSize);
        nfa->length = verify_u32(len);
        info->length = verify_u32(sizeof(RepeatInfo)
                                  + sizeof(u64a) * (rsi.patchSize + 1));
        copy_bytes(table, rsi.table);
    }
}
Exemplo n.º 2
0
enum RepeatType chooseRepeatType(const depth &repeatMin, const depth &repeatMax,
                                 u32 minPeriod, bool is_reset) {
    if (repeatMax.is_infinite()) {
        return REPEAT_FIRST;
    }

    if (repeatMin == depth(0) || is_reset) {
        return REPEAT_LAST;
    }

    // Cases with max < 64 can be handled with either bitmap or trailer. We use
    // whichever has smaller packed state.

    if (repeatMax < depth(64)) {
        u32 bitmap_len =
            packedSize(REPEAT_BITMAP, repeatMin, repeatMax, minPeriod);
        u32 trailer_len =
            packedSize(REPEAT_TRAILER, repeatMin, repeatMax, minPeriod);
        return bitmap_len <= trailer_len ? REPEAT_BITMAP : REPEAT_TRAILER;
    }

    if (repeatMin <= depth(64)) {
        return REPEAT_TRAILER;
    }

    u32 range_len = ~0U;
    if (repeatMax > repeatMin &&
        numRangeSlots(repeatMin, repeatMax) <= REPEAT_RANGE_MAX_SLOTS) {
        assert(numRangeSlots(repeatMin, repeatMax) < 256); // stored in u8
        range_len =
        streamStateSize(REPEAT_RANGE, repeatMin, repeatMax, minPeriod);
    }

    assert(repeatMax.is_finite());

    u32 sparse_len = ~0U;
    if (minPeriod > 6) {
        sparse_len =
        streamStateSize(REPEAT_SPARSE_OPTIMAL_P, repeatMin, repeatMax, minPeriod);
    }

    if (range_len != ~0U || sparse_len != ~0U) {
        return range_len < sparse_len ? REPEAT_RANGE : REPEAT_SPARSE_OPTIMAL_P;
    }

    return REPEAT_RING;
}
Exemplo n.º 3
0
RepeatStateInfo::RepeatStateInfo(enum RepeatType type, const depth &repeatMin,
                                 const depth &repeatMax, u32 minPeriod)
    : stateSize(0), packedCtrlSize(0), horizon(0), patchCount(0),
      patchSize(0), encodingSize(0), patchesOffset(0) {
    assert(repeatMin <= repeatMax);
    assert(repeatMax.is_reachable());
    assert(minPeriod || type != REPEAT_SPARSE_OPTIMAL_P);

    switch (type) {
    case REPEAT_FIRST:
        assert(repeatMin.is_finite());
        stateSize = 0; // everything is in the control block.
        horizon = repeatMin;
        packedCtrlSize = calcPackedBytes(horizon + 1);
        break;
    case REPEAT_LAST:
        assert(repeatMax.is_finite());
        stateSize = 0; // everything is in the control block.
        horizon = repeatMax + 1;
        packedCtrlSize = calcPackedBytes(horizon + 1);
        break;
    case REPEAT_RING:
        assert(repeatMax.is_finite());
        stateSize = mmbit_size(repeatMax + 1);
        horizon = repeatMax * 2 + 1; /* TODO: investigate tightening */
        // Packed offset member, plus two bytes for each ring index, reduced to
        // one byte each if they'll fit in eight bits.
        {
            u32 offset_len = calcPackedBytes(horizon + 1);
            u32 ring_indices_len = repeatMax < depth(254) ? 2 : 4;
            packedCtrlSize = offset_len + ring_indices_len;
        }
        break;
    case REPEAT_RANGE:
        assert(repeatMax.is_finite());
        assert(repeatMin < repeatMax);
        stateSize = numRangeSlots(repeatMin, repeatMax) * sizeof(u16);
        horizon = repeatMax * 2 + 1;
        // Packed offset member, plus one byte for the number of range
        // elements.
        packedCtrlSize = calcPackedBytes(horizon + 1) + 1;
        break;
    case REPEAT_BITMAP:
        stateSize = 0; // everything is in the control block.
        horizon = 0;   // unused
        packedCtrlSize = ROUNDUP_N(repeatMax + 1, 8) / 8;
        break;
    case REPEAT_SPARSE_OPTIMAL_P:
        assert(minPeriod);
        assert(repeatMax.is_finite());
        {
            u32 rv = repeatRecurTable(this, repeatMax, minPeriod);
            u32 repeatTmp = 0;
            if ((u32)repeatMax < minPeriod) {
                repeatTmp = repeatMax;
                patchCount = 1;
            } else {
                // find optimal patch size
                repeatTmp =
                    findOptimalPatchSize(this, repeatMax, minPeriod, rv);
                assert(patchCount < 65536);
            }
            DEBUG_PRINTF("repeat[%u %u], period=%u\n", (u32)repeatMin,
                         (u32)repeatMax, minPeriod);
            u64a maxVal = table[repeatTmp];
            encodingSize = calcPackedBytes(maxVal);
            patchSize = repeatTmp;
            assert(encodingSize <= 64);

            patchesOffset = mmbit_size(patchCount);
            stateSize = patchesOffset + encodingSize * patchCount;
            horizon = (repeatTmp * patchCount) * 2 + 1;
            u32 ring_indices_len = patchCount < depth(254) ? 2 : 4;
            packedCtrlSize = calcPackedBytes(horizon + 1) + ring_indices_len;
        }
        break;
    case REPEAT_TRAILER:
        assert(repeatMax.is_finite());
        assert(repeatMin <= depth(64));
        stateSize = 0; // everything is in the control block.
        horizon = repeatMax + 1;
        packedFieldSizes.resize(2);
        packedFieldSizes[0] = calcPackedBits(horizon + 1);
        packedFieldSizes[1] = repeatMin;
        packedCtrlSize = (packedFieldSizes[0] + packedFieldSizes[1] + 7U) / 8U;
        break;
    }
    DEBUG_PRINTF("stateSize=%u, packedCtrlSize=%u, horizon=%u\n", stateSize,
                 packedCtrlSize, horizon);

    assert(packedCtrlSize <= sizeof(RepeatControl));
}