LeechCraft  0.6.70-15082-g543737046d
Modular cross-platform feature rich live environment.
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 
19 namespace LC
20 {
21 namespace 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 
141  struct RegExpImpl
142  {
143 #if USE_PCRE
144  PCREWrapper PRx_;
145 #else
146  QRegExp Rx_;
147 #endif
148  };
149 
150  bool RegExp::IsFast ()
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 
218 QDataStream& 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 
226 QDataStream& 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 }
regexp.h
LC::Util::RegExp::Matches
bool Matches(const QString &) const
Definition: regexp.cpp:180
LC::Util::RegExpImpl::Rx_
QRegExp Rx_
Definition: regexp.cpp:158
LC::Util::RegExp::GetCaseSensitivity
Qt::CaseSensitivity GetCaseSensitivity() const
Definition: regexp.cpp:216
LC::Util::RegExp
Definition: regexp.h:34
LC::Util::RegExp::RegExp
RegExp()=default
operator>>
QDataStream & operator>>(QDataStream &in, LC::Util::RegExp &rx)
Definition: regexp.cpp:226
LC::Util::RegExpImpl
Definition: regexp.cpp:153
LC::Util::RegExp::GetPattern
QString GetPattern() const
Definition: regexp.cpp:204
LC::Util::RegExp::IsFast
static bool IsFast()
Definition: regexp.cpp:162
operator<<
QDataStream & operator<<(QDataStream &out, const LC::Util::RegExp &rx)
Definition: regexp.cpp:218
LC
Definition: constants.h:14