Cutelee  6.1.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  }
69  case QMetaType::QObjectStar: {
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  }
79  case QMetaType::QVariantList: {
80  return !variant.value<QVariantList>().isEmpty();
81  }
82  case QMetaType::QVariantHash: {
83  return !variant.value<QVariantHash>().isEmpty();
84  }
85  }
86 
87  return !getSafeString(variant).get().isEmpty();
88 }
89 
91 {
92  auto sret = input;
93  sret.setSafety(Cutelee::SafeString::IsSafe);
94  return sret;
95 }
96 
99 {
100  auto temp = input;
101  if (input.isSafe() || input.needsEscape())
102  return input;
103 
104  temp.setNeedsEscape(true);
105  return temp;
106 }
107 
109 {
110  if (input.userType() == qMetaTypeId<Cutelee::SafeString>()) {
111  return input.value<Cutelee::SafeString>();
112  } else {
113  return input.toString();
114  }
115 }
116 
117 bool Cutelee::isSafeString(const QVariant &input)
118 {
119  const auto type = input.userType();
120  return ((type == qMetaTypeId<Cutelee::SafeString>())
121  || type == QMetaType::QString);
122 }
123 
124 static QList<int> getPrimitives()
125 {
126  QList<int> primitives;
127  primitives << qMetaTypeId<Cutelee::SafeString>() << QMetaType::QString
128  << QMetaType::Bool << QMetaType::Int << QMetaType::Double
129  << QMetaType::Float << QMetaType::QDate << QMetaType::QTime
130  << QMetaType::QDateTime;
131  return primitives;
132 }
133 
135 {
136  static const auto primitives = getPrimitives();
137  return primitives.contains(input.userType());
138 }
139 
140 bool Cutelee::equals(const QVariant &lhs, const QVariant &rhs)
141 {
142  // TODO: Redesign...
143 
144  // QVariant doesn't use operator== to compare its held data, so we do it
145  // manually instead for SafeString.
146  auto equal = false;
147  if (lhs.userType() == qMetaTypeId<Cutelee::SafeString>()) {
148  if (rhs.userType() == qMetaTypeId<Cutelee::SafeString>()) {
149  equal = (lhs.value<Cutelee::SafeString>()
150  == rhs.value<Cutelee::SafeString>());
151  } else if (rhs.userType() == QMetaType::QString) {
152  equal = (lhs.value<Cutelee::SafeString>() == rhs.toString());
153  }
154  } else if (rhs.userType() == qMetaTypeId<Cutelee::SafeString>()
155  && lhs.userType() == QMetaType::QString) {
156  equal = (rhs.value<Cutelee::SafeString>() == lhs.toString());
157  } else if (rhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
158  if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
159  equal = (rhs.value<MetaEnumVariable>() == lhs.value<MetaEnumVariable>());
160  } else if (lhs.userType() == qMetaTypeId<int>()) {
161  equal = (rhs.value<MetaEnumVariable>() == lhs.value<int>());
162  }
163  } else if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
164  if (rhs.userType() == qMetaTypeId<int>()) {
165  equal = (lhs.value<MetaEnumVariable>() == rhs.value<int>());
166  }
167  } else {
168 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
169  equal = ((lhs == rhs) && (lhs.userType() == rhs.userType()));
170 #else
171  equal = lhs == rhs;
172 #endif
173  }
174  return equal;
175 }
176 
177 bool Cutelee::gt(const QVariant& lhs, const QVariant& rhs)
178 {
179 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
180  return lhs > rhs;
181 #else
182  return QVariant::compare(lhs, rhs) == QPartialOrdering::Greater;
183 #endif
184 }
185 
186 bool Cutelee::gte(const QVariant& lhs, const QVariant& rhs)
187 {
188 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
189  return lhs >= rhs;
190 #else
191  return equals(lhs, rhs) || gt(lhs, rhs);
192 #endif
193 }
194 
195 bool Cutelee::lt(const QVariant &lhs, const QVariant &rhs)
196 {
197 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
198  return lhs < rhs;
199 #else
200  return QVariant::compare(lhs, rhs) == QPartialOrdering::Less;
201 #endif
202 }
203 
204 
205 bool Cutelee::lte(const QVariant &lhs, const QVariant &rhs)
206 {
207 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
208  return lhs <= rhs;
209 #else
210  return equals(lhs, rhs) || lt(lhs, rhs);
211 #endif
212 }
213 
214 
215 std::pair<qreal,QString> Cutelee::calcFileSize(qreal size, int unitSystem, qreal multiplier)
216 {
217  std::pair<qreal,QString> ret;
218 
219  int _unitSystem = unitSystem;
220 
221  if ((_unitSystem != 2) && (_unitSystem != 10)) {
222  qWarning("%s", "Unrecognized file size unit system. Falling back to decimal unit system.");
223  _unitSystem = 10;
224  }
225 
226  if (size == 0.0) {
227  ret.first = 0.0;
228  ret.second = QStringLiteral("bytes");
229  return ret;
230  } else if ((size == 1.0) || (size == -1.0)) {
231  ret.first = 1.0;
232  ret.second = QStringLiteral("byte");
233  return ret;
234  }
235 
236  qreal _size = size * multiplier;
237 
238  const bool positiveValue = (_size > 0);
239 
240  if (!positiveValue) {
241  _size *= -1;
242  }
243 
244  static const QStringList binaryUnits({
245  QStringLiteral("bytes"),
246  QStringLiteral("KiB"),
247  QStringLiteral("MiB"),
248  QStringLiteral("GiB"),
249  QStringLiteral("TiB"),
250  QStringLiteral("PiB"),
251  QStringLiteral("EiB"),
252  QStringLiteral("ZiB"),
253  QStringLiteral("YiB")
254  });
255 
256  static const QStringList decimalUnits({
257  QStringLiteral("bytes"),
258  QStringLiteral("KB"),
259  QStringLiteral("MB"),
260  QStringLiteral("GB"),
261  QStringLiteral("TB"),
262  QStringLiteral("PB"),
263  QStringLiteral("EB"),
264  QStringLiteral("ZB"),
265  QStringLiteral("YB")
266  });
267 
268  int count = 0;
269  const qreal baseVal = (_unitSystem == 10) ? 1000.0f : 1024.0f;
270 #if FLT_EVAL_METHOD == 2
271  // Avoid that this is treated as long double, as the increased
272  // precision breaks the comparison below.
273  volatile qreal current = 1.0F;
274 #else
275  qreal current = 1.0f;
276 #endif
277  int units = decimalUnits.size();
278  while (count < units) {
279  current *= baseVal;
280  if (_size < current) {
281  break;
282  }
283  count++;
284  }
285 
286  if (count >= units) {
287  count = (units - 1);
288  }
289 
290  qreal devider = current/baseVal;
291  _size = _size/devider;
292 
293  if (!positiveValue) {
294  _size *= -1.0;
295  }
296 
297  ret.first = _size;
298  ret.second = (_unitSystem == 10) ? decimalUnits.at(count) : binaryUnits.at(count);
299 
300  return ret;
301 }
302 
303 Cutelee::SafeString Cutelee::toString(const QVariantList &list)
304 {
305  QString output(QLatin1Char('['));
306  auto it = list.constBegin();
307  const auto end = list.constEnd();
308  while (it != end) {
309  const auto item = *it;
310  if (isSafeString(item)) {
311  output += QStringLiteral("u\'")
312  + static_cast<QString>(getSafeString(item).get())
313  + QLatin1Char('\'');
314  }
315  if ((item.userType() == qMetaTypeId<int>())
316  || (item.userType() == qMetaTypeId<uint>())
317  || (item.userType() == qMetaTypeId<double>())
318  || (item.userType() == qMetaTypeId<float>())
319  || (item.userType() == qMetaTypeId<long long>())
320  || (item.userType() == qMetaTypeId<unsigned long long>())) {
321  output += item.toString();
322  }
323  if (item.userType() == qMetaTypeId<QVariantList>()) {
324  output
325  += static_cast<QString>(toString(item.value<QVariantList>()).get());
326  }
327  if ((it + 1) != end)
328  output += QStringLiteral(", ");
329  ++it;
330  }
331 
332  return output.append(QLatin1Char(']'));
333 }
A QString wrapper class for containing whether a string is safe or needs to be escaped.
Definition: safestring.h:92
bool needsEscape() const
Definition: safestring.cpp:56
bool isSafe() const
Definition: safestring.cpp:63
const NestedString & get() const
Definition: safestring.h:340
@ IsSafe
The string is safe and requires no further escaping.
Definition: safestring.h:98
bool equals(const QVariant &lhs, const QVariant &rhs)
Definition: util.cpp:140
QString unescapeStringLiteral(const QString &input)
Definition: util.cpp:31
std::pair< qreal, QString > calcFileSize(qreal size, int unitSystem=10, qreal multiplier=1.0)
Definition: util.cpp:215
bool supportedOutputType(const QVariant &input)
Definition: util.cpp:134
bool isSafeString(const QVariant &input)
Definition: util.cpp:117
Cutelee::SafeString getSafeString(const QVariant &input)
Definition: util.cpp:108
Cutelee::SafeString markSafe(const Cutelee::SafeString &input)
Definition: util.cpp:90
Cutelee::SafeString markForEscaping(const Cutelee::SafeString &input)
Definition: util.cpp:98
bool variantIsTrue(const QVariant &variant)
Definition: util.cpp:39
Utility functions used throughout Cutelee.