1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtCore module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QBYTEARRAYMATCHER_H
41#define QBYTEARRAYMATCHER_H
42
43#include <QtCore/qbytearray.h>
44
45#include <limits>
46
47QT_BEGIN_NAMESPACE
48
49
50class QByteArrayMatcherPrivate;
51
52class Q_CORE_EXPORT QByteArrayMatcher
53{
54public:
55 QByteArrayMatcher();
56 explicit QByteArrayMatcher(const QByteArray &pattern);
57 explicit QByteArrayMatcher(const char *pattern, int length);
58 QByteArrayMatcher(const QByteArrayMatcher &other);
59 ~QByteArrayMatcher();
60
61 QByteArrayMatcher &operator=(const QByteArrayMatcher &other);
62
63 void setPattern(const QByteArray &pattern);
64
65 int indexIn(const QByteArray &ba, int from = 0) const;
66 int indexIn(const char *str, int len, int from = 0) const;
67 inline QByteArray pattern() const
68 {
69 if (q_pattern.isNull())
70 return QByteArray(reinterpret_cast<const char*>(p.p), p.l);
71 return q_pattern;
72 }
73
74private:
75 QByteArrayMatcherPrivate *d;
76 QByteArray q_pattern;
77 struct Data {
78 uchar q_skiptable[256];
79 const uchar *p;
80 int l;
81 };
82 union {
83 uint dummy[256];
84 Data p;
85 };
86};
87
88class QStaticByteArrayMatcherBase
89{
90 Q_DECL_ALIGN(16)
91 struct Skiptable {
92 uchar data[256];
93 } m_skiptable;
94protected:
95 explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcherBase(const char *pattern, uint n) noexcept
96 : m_skiptable(generate(pattern, n)) {}
97 // compiler-generated copy/more ctors/assignment operators are ok!
98 // compiler-generated dtor is ok!
99
100 Q_CORE_EXPORT int indexOfIn(const char *needle, uint nlen, const char *haystack, int hlen, int from) const noexcept;
101
102private:
103 static Q_DECL_RELAXED_CONSTEXPR Skiptable generate(const char *pattern, uint n) noexcept
104 {
105 const auto uchar_max = (std::numeric_limits<uchar>::max)();
106 uchar max = n > uchar_max ? uchar_max : n;
107 Skiptable table = {
108 // this verbose initialization code aims to avoid some opaque error messages
109 // even on powerful compilers such as GCC 5.3. Even though for GCC a loop
110 // format can be found that v5.3 groks, it's probably better to go with this
111 // for the time being:
112 {
113 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
114 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
115 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
116 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
117 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
118 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
119 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
120 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
121
122 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
123 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
124 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
125 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
126 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
127 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
128 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
129 max, max, max, max, max, max, max, max, max, max, max, max, max, max, max, max,
130 }
131 };
132 pattern += n - max;
133 while (max--)
134 table.data[uchar(*pattern++)] = max;
135 return table;
136 }
137};
138
139template <uint N>
140class QStaticByteArrayMatcher : QStaticByteArrayMatcherBase
141{
142 char m_pattern[N];
143 Q_STATIC_ASSERT_X(N > 2, "QStaticByteArrayMatcher makes no sense for finding a single-char pattern");
144public:
145 explicit Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher(const char (&patternToMatch)[N]) noexcept
146 : QStaticByteArrayMatcherBase(patternToMatch, N - 1), m_pattern()
147 {
148 for (uint i = 0; i < N; ++i)
149 m_pattern[i] = patternToMatch[i];
150 }
151
152 int indexIn(const QByteArray &haystack, int from = 0) const noexcept
153 { return this->indexOfIn(m_pattern, N - 1, haystack.data(), haystack.size(), from); }
154 int indexIn(const char *haystack, int hlen, int from = 0) const noexcept
155 { return this->indexOfIn(m_pattern, N - 1, haystack, hlen, from); }
156
157 QByteArray pattern() const { return QByteArray(m_pattern, int(N - 1)); }
158};
159
160template <uint N>
161Q_DECL_RELAXED_CONSTEXPR QStaticByteArrayMatcher<N> qMakeStaticByteArrayMatcher(const char (&pattern)[N]) noexcept
162{ return QStaticByteArrayMatcher<N>(pattern); }
163
164QT_END_NAMESPACE
165
166#endif // QBYTEARRAYMATCHER_H
167