| 592 | */ |
| 593 | template<typename T, Concepts::ByteLike StorageType> |
| 594 | typename IO::CircularBuffer<T, StorageType>::MultiMatchResult IO::CircularBuffer<T, StorageType>:: |
| 595 | findFirstOfPatterns(const QVector<T>& patterns) const |
| 596 | { |
| 597 | Q_ASSERT(!patterns.isEmpty()); |
| 598 | |
| 599 | const qsizetype bufSize = size(); |
| 600 | if (patterns.isEmpty() || bufSize <= 0) [[unlikely]] |
| 601 | return {}; |
| 602 | |
| 603 | static constexpr int kMaxPatterns = 8; |
| 604 | Q_ASSERT(patterns.size() <= kMaxPatterns); |
| 605 | |
| 606 | struct PatInfo { |
| 607 | const StorageType* data; |
| 608 | qsizetype len; |
| 609 | }; |
| 610 | |
| 611 | PatInfo info[kMaxPatterns]; |
| 612 | const int patCount = qMin(patterns.size(), kMaxPatterns); |
| 613 | qsizetype minLen = bufSize; |
| 614 | for (int p = 0; p < patCount; ++p) { |
| 615 | info[p].data = reinterpret_cast<const StorageType*>(patterns[p].constData()); |
| 616 | info[p].len = patterns[p].size(); |
| 617 | if (info[p].len < minLen) |
| 618 | minLen = info[p].len; |
| 619 | } |
| 620 | |
| 621 | if (minLen <= 0 || bufSize < minLen) [[unlikely]] |
| 622 | return {}; |
| 623 | |
| 624 | const qsizetype head = m_head.load(std::memory_order_acquire); |
| 625 | const qsizetype mask = m_capacityMask; |
| 626 | const qsizetype scanEnd = bufSize - minLen + 1; |
| 627 | |
| 628 | auto matchAt = [&](qsizetype i, auto byteAt) -> int { |
| 629 | for (int p = 0; p < patCount; ++p) { |
| 630 | const auto pLen = info[p].len; |
| 631 | if (i + pLen > bufSize) |
| 632 | continue; |
| 633 | |
| 634 | const auto* pData = info[p].data; |
| 635 | bool match = true; |
| 636 | for (qsizetype j = 0; j < pLen; ++j) |
| 637 | if (byteAt(i + j) != pData[j]) { |
| 638 | match = false; |
| 639 | break; |
| 640 | } |
| 641 | |
| 642 | if (match) |
| 643 | return p; |
| 644 | } |
| 645 | |
| 646 | return -1; |
| 647 | }; |
| 648 | |
| 649 | auto scan = [&](auto byteAt) -> MultiMatchResult { |
| 650 | for (qsizetype i = 0; i < scanEnd; ++i) { |
| 651 | const int hit = matchAt(i, byteAt); |