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
39bool 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
118{
119 const auto type = input.userType();
120 return ((type == qMetaTypeId<Cutelee::SafeString>())
121 || type == QMetaType::QString);
122}
123
124static 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
140bool 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
177bool 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
186bool 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
195bool 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
205bool 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
215std::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
303Cutelee::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
const NestedString & get() const
Definition safestring.h:340
bool needsEscape() const
bool isSafe() const
@ 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.