LeechCraft  0.6.70-6645-gcd10d7e
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  * Boost Software License - Version 1.0 - August 17th, 2003
6  *
7  * Permission is hereby granted, free of charge, to any person or organization
8  * obtaining a copy of the software and accompanying documentation covered by
9  * this license (the "Software") to use, reproduce, display, distribute,
10  * execute, and transmit the Software, and to prepare derivative works of the
11  * Software, and to permit third-parties to whom the Software is furnished to
12  * do so, all subject to the following:
13  *
14  * The copyright notices in the Software and this entire statement, including
15  * the above license grant, this restriction and the following disclaimer,
16  * must be included in all copies of the Software, in whole or in part, and
17  * all derivative works of the Software, unless such copies or derivative
18  * works are solely in the form of machine-executable object code generated by
19  * a source language processor.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  * DEALINGS IN THE SOFTWARE.
28  **********************************************************************/
29 
30 #include "regexp.h"
31 #include <QDataStream>
32 #include <QtDebug>
33 
34 #ifdef USE_PCRE
35 #include <pcre.h>
36 #else
37 #include <QRegExp>
38 #endif
39 
40 namespace LeechCraft
41 {
42 namespace Util
43 {
44 #ifdef USE_PCRE
45 
46 #ifndef PCRE_STUDY_JIT_COMPILE
47 #define PCRE_STUDY_JIT_COMPILE 0
48 #endif
49 
50  class PCREWrapper
51  {
52  pcre *RE_;
53  pcre_extra *Extra_;
54 
55  QString Pattern_;
56  Qt::CaseSensitivity CS_;
57  public:
58  PCREWrapper ()
59  : RE_ (0)
60  , Extra_ (0)
61  {
62  }
63 
64  PCREWrapper (const QString& str, Qt::CaseSensitivity cs)
65  : RE_ (Compile (str, cs))
66  , Extra_ (0)
67  , Pattern_ (str)
68  , CS_ (cs)
69  {
70  if (RE_)
71  {
72  pcre_refcount (RE_, 1);
73  const char *error = 0;
74  const int opts = PCRE_STUDY_JIT_COMPILE;
75  Extra_ = pcre_study (RE_, opts, &error);
76  }
77  }
78 
79  PCREWrapper (const PCREWrapper& other)
80  : RE_ (0)
81  , Extra_ (0)
82  {
83  *this = other;
84  }
85 
86  PCREWrapper& operator= (const PCREWrapper& other)
87  {
88  if (RE_ && !pcre_refcount (RE_, -1))
89  {
90  FreeStudy ();
91  pcre_free (RE_);
92  }
93 
94  RE_ = other.RE_;
95  Extra_ = other.Extra_;
96  if (RE_)
97  pcre_refcount (RE_, 1);
98 
99  return *this;
100  }
101 
102  ~PCREWrapper ()
103  {
104  if (!RE_)
105  return;
106 
107  if (!pcre_refcount (RE_, -1))
108  {
109  FreeStudy ();
110  pcre_free (RE_);
111  }
112  }
113 
114  const QString& GetPattern () const
115  {
116  return Pattern_;
117  }
118 
119  Qt::CaseSensitivity GetCS () const
120  {
121  return CS_;
122  }
123 
124  int Exec (const QByteArray& utf8) const
125  {
126  return RE_ ? pcre_exec (RE_, Extra_, utf8.constData (), utf8.size (), 0, 0, NULL, 0) : -1;
127  }
128  private:
129  pcre* Compile (const QString& str, Qt::CaseSensitivity cs)
130  {
131  const char *error = 0;
132  int errOffset = 0;
133  int options = PCRE_UTF8;
134  if (cs == Qt::CaseInsensitive)
135  options |= PCRE_CASELESS;
136  auto re = pcre_compile (str.toUtf8 ().constData (), options, &error, &errOffset, NULL);
137  if (!re)
138  qWarning () << Q_FUNC_INFO
139  << "failed compiling"
140  << str
141  << error;
142  return re;
143  }
144 
145  void FreeStudy ()
146  {
147  if (Extra_)
148 #ifdef PCRE_CONFIG_JIT
149  pcre_free_study (Extra_);
150 #else
151  pcre_free (Extra_);
152 #endif
153  }
154  };
155 #endif
156 
157  namespace
158  {
159  struct RegExpRegisterGuard
160  {
161  RegExpRegisterGuard ()
162  {
163  qRegisterMetaType<RegExp> ("Util::RegExp");
164  qRegisterMetaTypeStreamOperators<RegExp> ();
165  }
166  } Guard;
167  }
168 
169  struct RegExpImpl
170  {
171 #if USE_PCRE
172  PCREWrapper PRx_;
173 #else
174  QRegExp Rx_;
175 #endif
176  };
177 
179  {
180 #ifdef USE_PCRE
181  return true;
182 #else
183  return false;
184 #endif
185  }
186 
187  RegExp::RegExp (const QString& str, Qt::CaseSensitivity cs)
188 #ifdef USE_PCRE
189  : Impl_ { new RegExpImpl { { str, cs } } }
190 #else
191  : Impl_ { new RegExpImpl { QRegExp { str, cs, QRegExp::RegExp } } }
192 #endif
193  {
194  }
195 
196  bool RegExp::Matches (const QString& str) const
197  {
198  if (!Impl_)
199  return {};
200 
201 #ifdef USE_PCRE
202  return Impl_->PRx_.Exec (str.toUtf8 ()) >= 0;
203 #else
204  return Impl_->Rx_.exactMatch (str);
205 #endif
206  }
207 
208  QString RegExp::GetPattern () const
209  {
210  if (!Impl_)
211  return {};
212 
213 #ifdef USE_PCRE
214  return Impl_->PRx_.GetPattern ();
215 #else
216  return Impl_->Rx_.pattern ();
217 #endif
218  }
219 
220  Qt::CaseSensitivity RegExp::GetCaseSensitivity () const
221  {
222  if (!Impl_)
223  return {};
224 
225 #ifdef USE_PCRE
226  return Impl_->PRx_.GetCS ();
227 #else
228  return Impl_->Rx_.caseSensitivity ();
229 #endif
230  }
231 }
232 }
233 
234 QDataStream& operator<< (QDataStream& out, const LeechCraft::Util::RegExp& rx)
235 {
236  out << static_cast<quint8> (1);
237  out << rx.GetPattern ()
238  << static_cast<quint8> (rx.GetCaseSensitivity ());
239  return out;
240 }
241 
242 QDataStream& operator>> (QDataStream& in, LeechCraft::Util::RegExp& rx)
243 {
244  quint8 version = 0;
245  in >> version;
246  if (version != 1)
247  {
248  qWarning () << Q_FUNC_INFO
249  << "unknown version"
250  << version;
251  return in;
252  }
253 
254  QString pattern;
255  quint8 cs;
256  in >> pattern
257  >> cs;
258 
259  rx = LeechCraft::Util::RegExp { pattern, static_cast<Qt::CaseSensitivity> (cs) };
260 
261  return in;
262 }
auto operator>>(const MV &value, const F &f) -> decltype(Bind(value, f))
Definition: monad.h:92
Qt::CaseSensitivity GetCaseSensitivity() const
Definition: regexp.cpp:220
QString GetPattern() const
Definition: regexp.cpp:208
QDataStream & operator<<(QDataStream &out, const LeechCraft::Util::RegExp &rx)
Definition: regexp.cpp:234
bool Matches(const QString &) const
Definition: regexp.cpp:196
static bool IsFast()
Definition: regexp.cpp:178