LeechCraft 0.6.70-16373-g319c272718
Modular cross-platform feature rich live environment.
Loading...
Searching...
No Matches
regexp.cpp
Go to the documentation of this file.
1/**********************************************************************
2 * LeechCraft - modular cross-platform feature rich internet client.
3 * Copyright (C) 2006-2014 Georg Rudoy
4 *
5 * Distributed under the Boost Software License, Version 1.0.
6 * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7 **********************************************************************/
8
9#include "regexp.h"
10#include <QDataStream>
11#include <QtDebug>
12
13#ifdef USE_PCRE
14#include <pcre.h>
15#else
16#include <QRegExp>
17#endif
18
19namespace LC
20{
21namespace Util
22{
23#ifdef USE_PCRE
24
25#ifndef PCRE_STUDY_JIT_COMPILE
26#define PCRE_STUDY_JIT_COMPILE 0
27#endif
28
29 class PCREWrapper
30 {
31 pcre *RE_ = nullptr;
32 pcre_extra *Extra_ = nullptr;
33
34 QString Pattern_;
35 Qt::CaseSensitivity CS_ = Qt::CaseSensitive;
36 public:
37 PCREWrapper () = default;
38
39 PCREWrapper (const QString& str, Qt::CaseSensitivity cs)
40 : RE_ (Compile (str, cs))
41 , Pattern_ (str)
42 , CS_ (cs)
43 {
44 if (RE_)
45 {
46 pcre_refcount (RE_, 1);
47 const char *error = 0;
48 const int opts = PCRE_STUDY_JIT_COMPILE;
49 Extra_ = pcre_study (RE_, opts, &error);
50 }
51 }
52
53 PCREWrapper (const PCREWrapper& other)
54 {
55 *this = other;
56 }
57
58 PCREWrapper& operator= (const PCREWrapper& other)
59 {
60 if (RE_ && !pcre_refcount (RE_, -1))
61 {
62 FreeStudy ();
63 pcre_free (RE_);
64 }
65
66 RE_ = other.RE_;
67 Extra_ = other.Extra_;
68 if (RE_)
69 pcre_refcount (RE_, 1);
70
71 return *this;
72 }
73
74 ~PCREWrapper ()
75 {
76 if (!RE_)
77 return;
78
79 if (!pcre_refcount (RE_, -1))
80 {
81 FreeStudy ();
82 pcre_free (RE_);
83 }
84 }
85
86 const QString& GetPattern () const
87 {
88 return Pattern_;
89 }
90
91 Qt::CaseSensitivity GetCS () const
92 {
93 return CS_;
94 }
95
96 int Exec (const QByteArray& utf8) const
97 {
98 return RE_ ? pcre_exec (RE_, Extra_, utf8.constData (), utf8.size (), 0, 0, NULL, 0) : -1;
99 }
100 private:
101 pcre* Compile (const QString& str, Qt::CaseSensitivity cs)
102 {
103 const char *error = 0;
104 int errOffset = 0;
105 int options = PCRE_UTF8;
106 if (cs == Qt::CaseInsensitive)
107 options |= PCRE_CASELESS;
108 auto re = pcre_compile (str.toUtf8 ().constData (), options, &error, &errOffset, NULL);
109 if (!re)
110 qWarning () << Q_FUNC_INFO
111 << "failed compiling"
112 << str
113 << error;
114 return re;
115 }
116
117 void FreeStudy ()
118 {
119 if (Extra_)
120#ifdef PCRE_CONFIG_JIT
121 pcre_free_study (Extra_);
122#else
123 pcre_free (Extra_);
124#endif
125 }
126 };
127#endif
128
129 namespace
130 {
131 struct RegExpRegisterGuard
132 {
133 RegExpRegisterGuard ()
134 {
135 qRegisterMetaType<RegExp> ("Util::RegExp");
136 qRegisterMetaTypeStreamOperators<RegExp> ();
137 }
138 } Guard;
139 }
140
142 {
143#if USE_PCRE
144 PCREWrapper PRx_;
145#else
146 QRegExp Rx_;
147#endif
148 };
149
151 {
152#ifdef USE_PCRE
153 return true;
154#else
155 return false;
156#endif
157 }
158
159 RegExp::RegExp (const QString& str, Qt::CaseSensitivity cs)
160#ifdef USE_PCRE
161 : Impl_ { new RegExpImpl { { str, cs } } }
162#else
163 : Impl_ { new RegExpImpl { QRegExp { str, cs, QRegExp::RegExp } } }
164#endif
165 {
166 }
167
168 bool RegExp::Matches (const QString& str) const
169 {
170 if (!Impl_)
171 return {};
172
173#ifdef USE_PCRE
174 return Impl_->PRx_.Exec (str.toUtf8 ()) >= 0;
175#else
176 return Impl_->Rx_.exactMatch (str);
177#endif
178 }
179
180 bool RegExp::Matches (const QByteArray& ba) const
181 {
182 if (!Impl_)
183 return {};
184
185#ifdef USE_PCRE
186 return Impl_->PRx_.Exec (ba) >= 0;
187#else
188 return Impl_->Rx_.exactMatch (ba);
189#endif
190 }
191
192 QString RegExp::GetPattern () const
193 {
194 if (!Impl_)
195 return {};
196
197#ifdef USE_PCRE
198 return Impl_->PRx_.GetPattern ();
199#else
200 return Impl_->Rx_.pattern ();
201#endif
202 }
203
204 Qt::CaseSensitivity RegExp::GetCaseSensitivity () const
205 {
206 if (!Impl_)
207 return {};
208
209#ifdef USE_PCRE
210 return Impl_->PRx_.GetCS ();
211#else
212 return Impl_->Rx_.caseSensitivity ();
213#endif
214 }
215}
216}
217
218QDataStream& operator<< (QDataStream& out, const LC::Util::RegExp& rx)
219{
220 out << static_cast<quint8> (1);
221 out << rx.GetPattern ()
222 << static_cast<quint8> (rx.GetCaseSensitivity ());
223 return out;
224}
225
226QDataStream& operator>> (QDataStream& in, LC::Util::RegExp& rx)
227{
228 quint8 version = 0;
229 in >> version;
230 if (version != 1)
231 {
232 qWarning () << Q_FUNC_INFO
233 << "unknown version"
234 << version;
235 return in;
236 }
237
238 QString pattern;
239 quint8 cs;
240 in >> pattern
241 >> cs;
242
243 rx = LC::Util::RegExp { pattern, static_cast<Qt::CaseSensitivity> (cs) };
244
245 return in;
246}
QString GetPattern() const
Definition regexp.cpp:192
Qt::CaseSensitivity GetCaseSensitivity() const
Definition regexp.cpp:204
RegExp()=default
bool Matches(const QString &) const
Definition regexp.cpp:168
static bool IsFast()
Definition regexp.cpp:150
Definition constants.h:15
QDataStream & operator<<(QDataStream &out, const LC::Util::RegExp &rx)
Definition regexp.cpp:218
QDataStream & operator>>(QDataStream &in, LC::Util::RegExp &rx)
Definition regexp.cpp:226