Cutelee  6.2.0
util.cpp
1 /*
2  This file is part of the Cutelee template system.
3 
4  Copyright (c) 2009,2010 Stephen Kelly <steveire@gmail.com>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Lesser General Public
8  License as published by the Free Software Foundation; either version
9  2.1 of the Licence, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public
17  License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 
19 */
20 
21 #include "util.h"
22 
23 #include "metaenumvariable_p.h"
24 #include "metatype.h"
25 
26 #include <QtCore/QStringList>
27 #include <QDebug>
28 
29 #include <cfloat>
30 
32 {
33  return input.mid(1, input.size() - 2)
34  .replace(QStringLiteral("\\\'"), QChar::fromLatin1('\''))
35  .replace(QStringLiteral("\\\""), QChar::fromLatin1('"'))
36  .replace(QStringLiteral("\\\\"), QChar::fromLatin1('\\'));
37 }
38 
39 bool Cutelee::variantIsTrue(const QVariant &variant)
40 {
41 
42  if (!variant.isValid())
43  return false;
44  switch (variant.userType()) {
45  case QMetaType::Bool: {
46  return variant.toBool();
47  }
48  case QMetaType::Int: {
49  return variant.value<int>() > 0;
50  }
51  case QMetaType::UInt: {
52  return variant.value<uint>() > 0;
53  }
54  case QMetaType::LongLong: {
55  return variant.value<qlonglong>() > 0;
56  }
57  case QMetaType::ULongLong: {
58  return variant.value<qulonglong>() > 0;
59  }
60  case QMetaType::Double: {
61  return variant.value<double>() > 0;
62  }
63  case QMetaType::Float: {
64  return variant.value<float>() > 0;
65  }
66  case QMetaType::Char: {
67  return variant.value<char>() > 0;
68  }
70  auto obj = variant.value<QObject *>();
71  if (!obj)
72  return false;
73 
74  if (obj->property("__true__").isValid()) {
75  return obj->property("__true__").toBool();
76  }
77  return true;
78  }
80  return !variant.value<QVariantList>().isEmpty();
81  }
83  return !variant.value<QVariantHash>().isEmpty();
84  }
86  return !variant.value<QVariantMap>().isEmpty();
87  }
88  }
89 
90  return !getSafeString(variant).get().isEmpty();
91 }
92 
94 {
95  auto sret = input;
96  sret.setSafety(Cutelee::SafeString::IsSafe);
97  return sret;
98 }
99 
102 {
103  auto temp = input;
104  if (input.isSafe() || input.needsEscape())
105  return input;
106 
107  temp.setNeedsEscape(true);
108  return temp;
109 }
110 
112 {
113  if (input.userType() == qMetaTypeId<Cutelee::SafeString>()) {
114  return input.value<Cutelee::SafeString>();
115  } else {
116  return input.toString();
117  }
118 }
119 
120 bool Cutelee::isSafeString(const QVariant &input)
121 {
122  const auto type = input.userType();
123  return ((type == qMetaTypeId<Cutelee::SafeString>())
124  || type == QMetaType::QString);
125 }
126 
127 static QList<int> getPrimitives()
128 {
129  QList<int> primitives;
130  primitives << qMetaTypeId<Cutelee::SafeString>() << QMetaType::QString
134  return primitives;
135 }
136 
138 {
139  static const auto primitives = getPrimitives();
140  return primitives.contains(input.userType());
141 }
142 
143 bool Cutelee::equals(const QVariant &lhs, const QVariant &rhs)
144 {
145  // TODO: Redesign...
146 
147  // QVariant doesn't use operator== to compare its held data, so we do it
148  // manually instead for SafeString.
149  auto equal = false;
150  if (lhs.userType() == qMetaTypeId<Cutelee::SafeString>()) {
151  if (rhs.userType() == qMetaTypeId<Cutelee::SafeString>()) {
152  equal = (lhs.value<Cutelee::SafeString>()
153  == rhs.value<Cutelee::SafeString>());
154  } else if (rhs.userType() == QMetaType::QString) {
155  equal = (lhs.value<Cutelee::SafeString>() == rhs.toString());
156  }
157  } else if (rhs.userType() == qMetaTypeId<Cutelee::SafeString>()
158  && lhs.userType() == QMetaType::QString) {
159  equal = (rhs.value<Cutelee::SafeString>() == lhs.toString());
160  } else if (rhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
161  if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
162  equal = (rhs.value<MetaEnumVariable>() == lhs.value<MetaEnumVariable>());
163  } else if (lhs.userType() == qMetaTypeId<int>()) {
164  equal = (rhs.value<MetaEnumVariable>() == lhs.value<int>());
165  }
166  } else if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
167  if (rhs.userType() == qMetaTypeId<int>()) {
168  equal = (lhs.value<MetaEnumVariable>() == rhs.value<int>());
169  }
170  } else {
171  equal = lhs == rhs;
172  }
173  return equal;
174 }
175 
176 bool Cutelee::gt(const QVariant& lhs, const QVariant& rhs)
177 {
178  return QVariant::compare(lhs, rhs) == QPartialOrdering::Greater;
179 }
180 
181 bool Cutelee::gte(const QVariant& lhs, const QVariant& rhs)
182 {
183  return equals(lhs, rhs) || gt(lhs, rhs);
184 }
185 
186 bool Cutelee::lt(const QVariant &lhs, const QVariant &rhs)
187 {
188  return QVariant::compare(lhs, rhs) == QPartialOrdering::Less;
189 }
190 
191 bool Cutelee::lte(const QVariant &lhs, const QVariant &rhs)
192 {
193  return equals(lhs, rhs) || lt(lhs, rhs);
194 }
195 
196 std::pair<qreal,QString> Cutelee::calcFileSize(qreal size, int unitSystem, qreal multiplier)
197 {
198  std::pair<qreal,QString> ret;
199 
200  int _unitSystem = unitSystem;
201 
202  if ((_unitSystem != 2) && (_unitSystem != 10)) {
203  qWarning("%s", "Unrecognized file size unit system. Falling back to decimal unit system.");
204  _unitSystem = 10;
205  }
206 
207  if (size == 0.0) {
208  ret.first = 0.0;
209  ret.second = QStringLiteral("bytes");
210  return ret;
211  } else if ((size == 1.0) || (size == -1.0)) {
212  ret.first = 1.0;
213  ret.second = QStringLiteral("byte");
214  return ret;
215  }
216 
217  qreal _size = size * multiplier;
218 
219  const bool positiveValue = (_size > 0);
220 
221  if (!positiveValue) {
222  _size *= -1;
223  }
224 
225  static const QStringList binaryUnits({
226  QStringLiteral("bytes"),
227  QStringLiteral("KiB"),
228  QStringLiteral("MiB"),
229  QStringLiteral("GiB"),
230  QStringLiteral("TiB"),
231  QStringLiteral("PiB"),
232  QStringLiteral("EiB"),
233  QStringLiteral("ZiB"),
234  QStringLiteral("YiB")
235  });
236 
237  static const QStringList decimalUnits({
238  QStringLiteral("bytes"),
239  QStringLiteral("KB"),
240  QStringLiteral("MB"),
241  QStringLiteral("GB"),
242  QStringLiteral("TB"),
243  QStringLiteral("PB"),
244  QStringLiteral("EB"),
245  QStringLiteral("ZB"),
246  QStringLiteral("YB")
247  });
248 
249  int count = 0;
250  const qreal baseVal = (_unitSystem == 10) ? 1000.0f : 1024.0f;
251 #if FLT_EVAL_METHOD == 2
252  // Avoid that this is treated as long double, as the increased
253  // precision breaks the comparison below.
254  volatile qreal current = 1.0F;
255 #else
256  qreal current = 1.0f;
257 #endif
258  int units = decimalUnits.size();
259  while (count < units) {
260  current *= baseVal;
261  if (_size < current) {
262  break;
263  }
264  count++;
265  }
266 
267  if (count >= units) {
268  count = (units - 1);
269  }
270 
271  qreal devider = current/baseVal;
272  _size = _size/devider;
273 
274  if (!positiveValue) {
275  _size *= -1.0;
276  }
277 
278  ret.first = _size;
279  ret.second = (_unitSystem == 10) ? decimalUnits.at(count) : binaryUnits.at(count);
280 
281  return ret;
282 }
283 
284 Cutelee::SafeString Cutelee::toString(const QVariantList &list)
285 {
286  QString output(QLatin1Char('['));
287  auto it = list.constBegin();
288  const auto end = list.constEnd();
289  while (it != end) {
290  const auto item = *it;
291  if (isSafeString(item)) {
292  output += QStringLiteral("u\'")
293  + static_cast<QString>(getSafeString(item).get())
294  + QLatin1Char('\'');
295  }
296  if ((item.userType() == qMetaTypeId<int>())
297  || (item.userType() == qMetaTypeId<uint>())
298  || (item.userType() == qMetaTypeId<double>())
299  || (item.userType() == qMetaTypeId<float>())
300  || (item.userType() == qMetaTypeId<long long>())
301  || (item.userType() == qMetaTypeId<unsigned long long>())) {
302  output += item.toString();
303  }
304  if (item.userType() == qMetaTypeId<QVariantList>()) {
305  output
306  += static_cast<QString>(toString(item.value<QVariantList>()).get());
307  }
308  if ((it + 1) != end)
309  output += QStringLiteral(", ");
310  ++it;
311  }
312 
313  return output.append(QLatin1Char(']'));
314 }
bool variantIsTrue(const QVariant &variant)
Definition: util.cpp:39
QString & append(QChar ch)
Cutelee::SafeString markSafe(const Cutelee::SafeString &input)
Definition: util.cpp:93
qsizetype size() const const
T value() const const
bool supportedOutputType(const QVariant &input)
Definition: util.cpp:137
bool equals(const QVariant &lhs, const QVariant &rhs)
Definition: util.cpp:143
qsizetype size() const const
bool isSafeString(const QVariant &input)
Definition: util.cpp:120
Cutelee::SafeString markForEscaping(const Cutelee::SafeString &input)
Definition: util.cpp:101
QString unescapeStringLiteral(const QString &input)
Definition: util.cpp:31
QPartialOrdering compare(const QVariant &lhs, const QVariant &rhs)
QVariant property(const char *name) const const
QChar fromLatin1(char c)
bool isEmpty() const const
Utility functions used throughout Cutelee.
A QString wrapper class for containing whether a string is safe or needs to be escaped.
Definition: safestring.h:91
int userType() const const
QString mid(qsizetype position, qsizetype n) const const
bool toBool() const const
bool isValid() const const
std::pair< qreal, QString > calcFileSize(qreal size, int unitSystem=10, qreal multiplier=1.0)
Definition: util.cpp:196
bool isSafe() const
Definition: safestring.cpp:63
bool needsEscape() const
Definition: safestring.cpp:56
QString toString() const const
const NestedString & get() const
Definition: safestring.h:325
Cutelee::SafeString getSafeString(const QVariant &input)
Definition: util.cpp:111
The string is safe and requires no further escaping.
Definition: safestring.h:98