File indexing completed on 2026-09-08 09:20:07
0001
0002
0003
0004
0005 #ifndef QBYTEARRAYMATCHER_H
0006 #define QBYTEARRAYMATCHER_H
0007
0008 #include <QtCore/qbytearray.h>
0009
0010 #include <QtCore/q20algorithm.h>
0011 #include <iterator>
0012 #include <limits>
0013
0014 QT_BEGIN_NAMESPACE
0015
0016
0017 class QByteArrayMatcherPrivate;
0018
0019 class Q_CORE_EXPORT QByteArrayMatcher
0020 {
0021 public:
0022 QByteArrayMatcher();
0023 explicit QByteArrayMatcher(const QByteArray &pattern);
0024 explicit QByteArrayMatcher(QByteArrayView pattern)
0025 : QByteArrayMatcher(pattern.data(), pattern.size())
0026 {}
0027 explicit QByteArrayMatcher(const char *pattern, qsizetype length = -1);
0028 QByteArrayMatcher(const QByteArrayMatcher &other);
0029 ~QByteArrayMatcher();
0030
0031 QByteArrayMatcher &operator=(const QByteArrayMatcher &other);
0032
0033 void setPattern(const QByteArray &pattern);
0034
0035 #if QT_CORE_REMOVED_SINCE(6, 3)
0036 qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const;
0037 #else
0038 Q_WEAK_OVERLOAD
0039 qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const
0040 { return indexIn(QByteArrayView{ba}, from); }
0041 #endif
0042 qsizetype indexIn(const char *str, qsizetype len, qsizetype from = 0) const;
0043 qsizetype indexIn(QByteArrayView data, qsizetype from = 0) const;
0044 inline QByteArray pattern() const
0045 {
0046 if (q_pattern.isNull())
0047 return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
0048 return q_pattern;
0049 }
0050
0051 private:
0052 QByteArrayMatcherPrivate *d;
0053 QByteArray q_pattern;
0054 struct Data {
0055 uchar q_skiptable[256];
0056 const uchar *p;
0057 qsizetype l;
0058 };
0059 union {
0060 uint dummy[256];
0061 Data p;
0062 };
0063 };
0064
0065 class QStaticByteArrayMatcherBase
0066 {
0067 alignas(16)
0068 struct Skiptable {
0069 uchar data[256];
0070 } m_skiptable;
0071 protected:
0072 explicit constexpr QStaticByteArrayMatcherBase(const char *pattern, size_t n) noexcept
0073 : m_skiptable(generate(pattern, n)) {}
0074
0075 ~QStaticByteArrayMatcherBase() = default;
0076
0077 #if QT_CORE_REMOVED_SINCE(6, 3) && QT_POINTER_SIZE != 4
0078 Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept;
0079 #endif
0080 Q_CORE_EXPORT qsizetype indexOfIn(const char *needle, size_t nlen,
0081 const char *haystack, qsizetype hlen,
0082 qsizetype from) const noexcept;
0083
0084 private:
0085 static constexpr Skiptable generate(const char *pattern, size_t n) noexcept
0086 {
0087 const auto uchar_max = (std::numeric_limits<uchar>::max)();
0088 uchar max = n > uchar_max ? uchar_max : uchar(n);
0089 Skiptable table = {};
0090 q20::fill(std::begin(table.data), std::end(table.data), max);
0091 pattern += n - max;
0092 while (max--)
0093 table.data[uchar(*pattern++)] = max;
0094 return table;
0095 }
0096 };
0097
0098 template <size_t N>
0099 class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
0100 {
0101 char m_pattern[N];
0102
0103 static_assert(N > 2, "QStaticByteArrayMatcher makes no sense for finding a single-char pattern");
0104 public:
0105 explicit constexpr QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
0106 : QStaticByteArrayMatcherBase(patternToMatch, N - 1), m_pattern()
0107 {
0108 for (size_t i = 0; i < N; ++i)
0109 m_pattern[i] = patternToMatch[i];
0110 }
0111
0112 Q_WEAK_OVERLOAD
0113 qsizetype indexIn(const QByteArray &haystack, qsizetype from = 0) const noexcept
0114 { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
0115 qsizetype indexIn(const char *haystack, qsizetype hlen, qsizetype from = 0) const noexcept
0116 { return this->indexOfIn(m_pattern, N - 1, haystack, hlen, from); }
0117 qsizetype indexIn(QByteArrayView haystack, qsizetype from = 0) const noexcept
0118 { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
0119
0120 QByteArray pattern() const { return QByteArray(m_pattern, qsizetype(N - 1)); }
0121 };
0122
0123 template <size_t N>
0124 constexpr QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
0125 { return QStaticByteArrayMatcher<N>(pattern); }
0126
0127 QT_END_NAMESPACE
0128
0129 #endif