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

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