1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QBYTEARRAYMATCHER_H
5#define QBYTEARRAYMATCHER_H
6
7#include <QtCore/qbytearray.h>
8
9#include <QtCore/q20algorithm.h>
10#include <iterator>
11#include <limits>
12
13QT_BEGIN_NAMESPACE
14
15
16class QByteArrayMatcherPrivate;
17
18class Q_CORE_EXPORT QByteArrayMatcher
19{
20public:
21 QByteArrayMatcher();
22 explicit QByteArrayMatcher(const QByteArray &pattern);
23 explicit QByteArrayMatcher(QByteArrayView pattern)
24 : QByteArrayMatcher(pattern.data(), pattern.size())
25 {}
26 explicit QByteArrayMatcher(const char *pattern, qsizetype length = -1);
27 QByteArrayMatcher(const QByteArrayMatcher &other);
28 ~QByteArrayMatcher();
29
30 QByteArrayMatcher &operator=(const QByteArrayMatcher &other);
31
32 void setPattern(const QByteArray &pattern);
33
34#if QT_CORE_REMOVED_SINCE(6, 3)
35 qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const;
36#else
37 Q_WEAK_OVERLOAD
38 qsizetype indexIn(const QByteArray &ba, qsizetype from = 0) const
39 { return indexIn(data: QByteArrayView{ba}, from); }
40#endif
41 qsizetype indexIn(const char *str, qsizetype len, qsizetype from = 0) const;
42 qsizetype indexIn(QByteArrayView data, qsizetype from = 0) const;
43 inline QByteArray pattern() const
44 {
45 if (q_pattern.isNull())
46 return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
47 return q_pattern;
48 }
49
50private:
51 QByteArrayMatcherPrivate *d;
52 QByteArray q_pattern;
53 struct Data {
54 uchar q_skiptable[256];
55 const uchar *p;
56 qsizetype l;
57 };
58 union {
59 uint dummy[256];
60 Data p;
61 };
62};
63
64class QStaticByteArrayMatcherBase
65{
66 alignas(16)
67 struct Skiptable {
68 uchar data[256];
69 } m_skiptable;
70protected:
71 explicit constexpr QStaticByteArrayMatcherBase(const char *pattern, size_t n) noexcept
72 : m_skiptable(generate(pattern, n)) {}
73 // compiler-generated copy/more ctors/assignment operators are ok!
74 ~QStaticByteArrayMatcherBase() = default;
75
76#if QT_CORE_REMOVED_SINCE(6, 3) && QT_POINTER_SIZE != 4
77 Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept;
78#endif
79 Q_CORE_EXPORT qsizetype indexOfIn(const char *needle, size_t nlen,
80 const char *haystack, qsizetype hlen,
81 qsizetype from) const noexcept;
82
83private:
84 static constexpr Skiptable generate(const char *pattern, size_t n) noexcept
85 {
86 const auto uchar_max = (std::numeric_limits<uchar>::max)();
87 uchar max = n > uchar_max ? uchar_max : uchar(n);
88 Skiptable table = {};
89 q20::fill(first: std::begin(arr&: table.data), last: std::end(arr&: table.data), value: max);
90 pattern += n - max;
91 while (max--)
92 table.data[uchar(*pattern++)] = max;
93 return table;
94 }
95};
96
97template <size_t N>
98class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
99{
100 char m_pattern[N];
101 // N includes the terminating '\0'!
102 static_assert(N > 2, "QStaticByteArrayMatcher makes no sense for finding a single-char pattern");
103public:
104 explicit constexpr QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
105 : QStaticByteArrayMatcherBase(patternToMatch, N - 1), m_pattern()
106 {
107 for (size_t i = 0; i < N; ++i)
108 m_pattern[i] = patternToMatch[i];
109 }
110
111 Q_WEAK_OVERLOAD
112 qsizetype indexIn(const QByteArray &haystack, qsizetype from = 0) const noexcept
113 { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
114 qsizetype indexIn(const char *haystack, qsizetype hlen, qsizetype from = 0) const noexcept
115 { return this->indexOfIn(m_pattern, N - 1, haystack, hlen, from); }
116 qsizetype indexIn(QByteArrayView haystack, qsizetype from = 0) const noexcept
117 { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
118
119 QByteArray pattern() const { return QByteArray(m_pattern, qsizetype(N - 1)); }
120};
121
122template <size_t N>
123constexpr QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
124{ return QStaticByteArrayMatcher<N>(pattern); }
125
126QT_END_NAMESPACE
127
128#endif // QBYTEARRAYMATCHER_H
129

source code of qtbase/src/corelib/text/qbytearraymatcher.h