Qt 4.8
qstringmatcher.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qstringmatcher.h"
43 
45 
46 static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs)
47 {
48  int l = qMin(len, 255);
49  memset(skiptable, l, 256*sizeof(uchar));
50  uc += len - l;
51  if (cs == Qt::CaseSensitive) {
52  while (l--) {
53  skiptable[*uc & 0xff] = l;
54  uc++;
55  }
56  } else {
57  const ushort *start = uc;
58  while (l--) {
59  skiptable[foldCase(uc, start) & 0xff] = l;
60  uc++;
61  }
62  }
63 }
64 
65 static inline int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl,
66  const uchar *skiptable, Qt::CaseSensitivity cs)
67 {
68  if (pl == 0)
69  return index > (int)l ? -1 : index;
70  const uint pl_minus_one = pl - 1;
71 
72  register const ushort *current = uc + index + pl_minus_one;
73  const ushort *end = uc + l;
74  if (cs == Qt::CaseSensitive) {
75  while (current < end) {
76  uint skip = skiptable[*current & 0xff];
77  if (!skip) {
78  // possible match
79  while (skip < pl) {
80  if (*(current - skip) != puc[pl_minus_one-skip])
81  break;
82  skip++;
83  }
84  if (skip > pl_minus_one) // we have a match
85  return (current - uc) - pl_minus_one;
86 
87  // in case we don't have a match we are a bit inefficient as we only skip by one
88  // when we have the non matching char in the string.
89  if (skiptable[*(current - skip) & 0xff] == pl)
90  skip = pl - skip;
91  else
92  skip = 1;
93  }
94  if (current > end - skip)
95  break;
96  current += skip;
97  }
98  } else {
99  while (current < end) {
100  uint skip = skiptable[foldCase(current, uc) & 0xff];
101  if (!skip) {
102  // possible match
103  while (skip < pl) {
104  if (foldCase(current - skip, uc) != foldCase(puc + pl_minus_one - skip, puc))
105  break;
106  skip++;
107  }
108  if (skip > pl_minus_one) // we have a match
109  return (current - uc) - pl_minus_one;
110  // in case we don't have a match we are a bit inefficient as we only skip by one
111  // when we have the non matching char in the string.
112  if (skiptable[foldCase(current - skip, uc) & 0xff] == pl)
113  skip = pl - skip;
114  else
115  skip = 1;
116  }
117  if (current > end - skip)
118  break;
119  current += skip;
120  }
121  }
122  return -1; // not found
123 }
124 
155  : d_ptr(0), q_cs(Qt::CaseSensitive)
156 {
157  qMemSet(q_data, 0, sizeof(q_data));
158 }
159 
167  : d_ptr(0), q_pattern(pattern), q_cs(cs)
168 {
169  p.uc = pattern.unicode();
170  p.len = pattern.size();
171  bm_init_skiptable((const ushort *)p.uc, p.len, p.q_skiptable, cs);
172 }
173 
182  : d_ptr(0), q_cs(cs)
183 {
184  p.uc = uc;
185  p.len = len;
186  bm_init_skiptable((const ushort *)p.uc, len, p.q_skiptable, cs);
187 }
188 
193  : d_ptr(0)
194 {
195  operator=(other);
196 }
197 
202 {
203 }
204 
209 {
210  if (this != &other) {
211  q_pattern = other.q_pattern;
212  q_cs = other.q_cs;
213  memcpy(q_data, other.q_data, sizeof(q_data));
214  }
215  return *this;
216 }
217 
225 {
226  q_pattern = pattern;
227  p.uc = pattern.unicode();
228  p.len = pattern.size();
229  bm_init_skiptable((const ushort *)pattern.unicode(), pattern.size(), p.q_skiptable, q_cs);
230 }
231 
245 {
246  if (!q_pattern.isEmpty())
247  return q_pattern;
248  return QString(p.uc, p.len);
249 }
250 
258 {
259  if (cs == q_cs)
260  return;
262  q_cs = cs;
263 }
264 
274 int QStringMatcher::indexIn(const QString &str, int from) const
275 {
276  if (from < 0)
277  from = 0;
278  return bm_find((const ushort *)str.unicode(), str.size(), from,
279  (const ushort *)p.uc, p.len,
280  p.q_skiptable, q_cs);
281 }
282 
298 int QStringMatcher::indexIn(const QChar *str, int length, int from) const
299 {
300  if (from < 0)
301  from = 0;
302  return bm_find((const ushort *)str, length, from,
303  (const ushort *)p.uc, p.len,
304  p.q_skiptable, q_cs);
305 }
306 
323  const QChar *haystack, int haystackLen, int haystackOffset,
324  const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
325 {
326  uchar skiptable[256];
327  bm_init_skiptable((const ushort *)needle, needleLen, skiptable, cs);
328  if (haystackOffset < 0)
329  haystackOffset = 0;
330  return bm_find((const ushort *)haystack, haystackLen, haystackOffset,
331  (const ushort *)needle, needleLen, skiptable, cs);
332 }
333 
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static void bm_init_skiptable(const ushort *uc, int len, uchar *skiptable, Qt::CaseSensitivity cs)
uint q_data[256]
~QStringMatcher()
Destroys the string matcher.
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
The QStringMatcher class holds a sequence of characters that can be quickly matched in a Unicode stri...
Qt::CaseSensitivity q_cs
unsigned char uchar
Definition: qglobal.h:994
void setCaseSensitivity(Qt::CaseSensitivity cs)
Sets the case sensitivity setting of this string matcher to cs.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
const QChar * unicode() const
Returns a &#39;\0&#39;-terminated Unicode representation of the string.
Definition: qstring.h:706
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QStringMatcherPrivate * d_ptr
unsigned int uint
Definition: qglobal.h:996
QString pattern() const
Returns the string pattern that this string matcher will search for.
static int bm_find(const ushort *uc, uint l, int index, const ushort *puc, uint pl, const uchar *skiptable, Qt::CaseSensitivity cs)
static uint foldCase(const ushort *ch, const ushort *start)
Definition: qchar.cpp:1380
CaseSensitivity
Definition: qnamespace.h:1451
void * qMemSet(void *dest, int c, size_t n)
Definition: qglobal.cpp:2509
unsigned short ushort
Definition: qglobal.h:995
void setPattern(const QString &pattern)
Sets the string that this string matcher will search for to pattern.
Definition: qnamespace.h:54
QFactoryLoader * l
QStringMatcher()
Constructs an empty string matcher that won&#39;t match anything.
int indexIn(const QString &str, int from=0) const
Searches the string str from character position from (default 0, i.e.
quint16 index
static const KeyPair *const end
int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int haystackOffset, const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
QStringMatcher & operator=(const QStringMatcher &other)
Assigns the other string matcher to this string matcher.