patternlist.cpp
1 //------------------------------------------------------------------------------
2 // patternlist.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2014 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "patternlist.h"
24 
25 #include "log.h"
26 #include <QDataStream>
27 #include <QDebug>
28 #include <QIODevice>
29 
30 bool PatternList::isExactMatchAny(const QString &candidate) const
31 {
32  for (const auto &matcher : *this)
33  {
34  auto match = matcher.match(candidate, 0, QRegularExpression::NormalMatch, QRegularExpression::AnchoredMatchOption);
35  if (match.hasMatch() && match.capturedLength(0) == candidate.length())
36  {
37  return true;
38  }
39  }
40  return false;
41 }
42 
43 PatternList PatternList::deserializeQVariant(const QVariant &var)
44 {
45  PatternList result;
46  for (const QVariant &element : var.toList())
47  {
48  if (element.canConvert<Pattern>())
49  {
50  result << element.value<Pattern>();
51  }
52  else if (element.canConvert<QRegularExpression>())
53  {
54  // Should never be reached, but if it is this is better than losing the pattern entirely
55  result << element.toRegularExpression();
56  }
57  else
58  {
59  // Qt6 technically has QRegExp as part of QtCore5Compat module, but
60  // it would be silly to bring in the whole library for one type so
61  // lets read the old setting raw. We could of course use QRegExp on
62  // Qt5 builds, but why maintain two branches?
63 
64  QByteArray rawData;
65  {
66  QDataStream stream(&rawData, QIODevice::WriteOnly);
67  // This is the version that QSettings uses so probably good enough for us to keep things simple
68  stream.setVersion(QDataStream::Qt_4_0);
69  stream << element;
70  }
71 
72  QDataStream stream(&rawData, QIODevice::ReadOnly);
73  stream.setVersion(QDataStream::Qt_4_0);
74 
75  constexpr quint32 REGEXP_TYPE = 27;
76  quint32 type = 0;
77  stream >> type;
78  if (stream.status() != QDataStream::Ok)
79  {
80  qDebug() << "Attempt to migrate QRegExp could not read variant type";
81  continue;
82  }
83  if (type != REGEXP_TYPE)
84  {
85  qDebug() << "Attempt to migrate QRegExp encounter unexpected type:" << type;
86  continue;
87  }
88 
89  constexpr quint8 REGEXP_SYNTAX_WILDCARD = 1;
90 
91  QString regex;
92  quint8 caseSensitivity = 0;
93  quint8 syntax = 0;
94  quint8 minimal = 0;
95  stream >> regex >> caseSensitivity >> syntax >> minimal;
96  if (stream.status() != QDataStream::Ok)
97  {
98  qDebug() << "Attempt to migrate QRegExp could not read contents";
99  continue;
100  }
101 
102  result << Pattern(regex, caseSensitivity == Qt::CaseSensitive ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption, syntax == REGEXP_SYNTAX_WILDCARD ? Pattern::Wildcard : Pattern::RegExp);
103  }
104  }
105  return result;
106 }
107 
108 QVariant PatternList::serializeQVariant() const
109 {
110  QVariantList var;
111  for (const auto &pattern : *this)
112  {
113  var << QVariant::fromValue(pattern);
114  }
115  return var;
116 }