File indexing completed on 2025-02-09 04:28:41

0001 /*
0002   This file is part of the KTextTemplate library
0003 
0004   SPDX-FileCopyrightText: 2009, 2010 Stephen Kelly <steveire@gmail.com>
0005 
0006   SPDX-License-Identifier: LGPL-2.1-or-later
0007 
0008 */
0009 
0010 #include "util.h"
0011 
0012 #include "metaenumvariable_p.h"
0013 
0014 #include <QStringList>
0015 
0016 QString KTextTemplate::unescapeStringLiteral(const QString &input)
0017 {
0018     return input.mid(1, input.size() - 2)
0019         .replace(QStringLiteral("\\\'"), QChar::fromLatin1('\''))
0020         .replace(QStringLiteral("\\\""), QChar::fromLatin1('"'))
0021         .replace(QStringLiteral("\\\\"), QChar::fromLatin1('\\'));
0022 }
0023 
0024 bool KTextTemplate::variantIsTrue(const QVariant &variant)
0025 {
0026     if (!variant.isValid())
0027         return false;
0028     switch (variant.userType()) {
0029     case QMetaType::Bool: {
0030         return variant.value<bool>();
0031     }
0032     case QMetaType::Int: {
0033         return variant.value<int>() > 0;
0034     }
0035     case QMetaType::UInt: {
0036         return variant.value<uint>() > 0;
0037     }
0038     case QMetaType::LongLong: {
0039         return variant.value<qlonglong>() > 0;
0040     }
0041     case QMetaType::ULongLong: {
0042         return variant.value<qulonglong>() > 0;
0043     }
0044     case QMetaType::Double: {
0045         return variant.value<double>() > 0;
0046     }
0047     case QMetaType::Float: {
0048         return variant.value<float>() > 0;
0049     }
0050     case QMetaType::Char: {
0051         return variant.value<char>() > 0;
0052     }
0053     case QMetaType::QObjectStar: {
0054         auto obj = variant.value<QObject *>();
0055         if (!obj)
0056             return false;
0057 
0058         if (obj->property("__true__").isValid()) {
0059             return obj->property("__true__").value<bool>();
0060         }
0061         return true;
0062     }
0063     case QMetaType::QVariantList: {
0064         return !variant.value<QVariantList>().isEmpty();
0065     }
0066     case QMetaType::QVariantHash: {
0067         return !variant.value<QVariantHash>().isEmpty();
0068     }
0069     }
0070 
0071     return !getSafeString(variant).get().isEmpty();
0072 }
0073 
0074 KTextTemplate::SafeString KTextTemplate::markSafe(const KTextTemplate::SafeString &input)
0075 {
0076     auto sret = input;
0077     sret.setSafety(KTextTemplate::SafeString::IsSafe);
0078     return sret;
0079 }
0080 
0081 KTextTemplate::SafeString KTextTemplate::markForEscaping(const KTextTemplate::SafeString &input)
0082 {
0083     auto temp = input;
0084     if (input.isSafe() || input.needsEscape())
0085         return input;
0086 
0087     temp.setNeedsEscape(true);
0088     return temp;
0089 }
0090 
0091 KTextTemplate::SafeString KTextTemplate::getSafeString(const QVariant &input)
0092 {
0093     if (input.userType() == qMetaTypeId<KTextTemplate::SafeString>()) {
0094         return input.value<KTextTemplate::SafeString>();
0095     }
0096     return input.value<QString>();
0097 }
0098 
0099 bool KTextTemplate::isSafeString(const QVariant &input)
0100 {
0101     const auto type = input.userType();
0102     return ((type == qMetaTypeId<KTextTemplate::SafeString>()) || type == QMetaType::QString);
0103 }
0104 
0105 static QList<int> getPrimitives()
0106 {
0107     QList<int> primitives;
0108     primitives << qMetaTypeId<KTextTemplate::SafeString>() << QMetaType::QString << QMetaType::Bool << QMetaType::Int << QMetaType::Double << QMetaType::Float
0109                << QMetaType::QDate << QMetaType::QTime << QMetaType::QDateTime;
0110     return primitives;
0111 }
0112 
0113 bool KTextTemplate::supportedOutputType(const QVariant &input)
0114 {
0115     static const auto primitives = getPrimitives();
0116     return primitives.contains(input.userType());
0117 }
0118 
0119 bool KTextTemplate::equals(const QVariant &lhs, const QVariant &rhs)
0120 {
0121     // TODO: Redesign...
0122 
0123     // QVariant doesn't use operator== to compare its held data, so we do it
0124     // manually instead for SafeString.
0125     auto equal = false;
0126     if (lhs.userType() == qMetaTypeId<KTextTemplate::SafeString>()) {
0127         if (rhs.userType() == qMetaTypeId<KTextTemplate::SafeString>()) {
0128             equal = (lhs.value<KTextTemplate::SafeString>() == rhs.value<KTextTemplate::SafeString>());
0129         } else if (rhs.userType() == QMetaType::QString) {
0130             equal = (lhs.value<KTextTemplate::SafeString>() == rhs.value<QString>());
0131         }
0132     } else if (rhs.userType() == qMetaTypeId<KTextTemplate::SafeString>() && lhs.userType() == QMetaType::QString) {
0133         equal = (rhs.value<KTextTemplate::SafeString>() == lhs.value<QString>());
0134     } else if (rhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
0135         if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
0136             equal = (rhs.value<MetaEnumVariable>() == lhs.value<MetaEnumVariable>());
0137         } else if (lhs.userType() == qMetaTypeId<int>()) {
0138             equal = (rhs.value<MetaEnumVariable>() == lhs.value<int>());
0139         }
0140     } else if (lhs.userType() == qMetaTypeId<MetaEnumVariable>()) {
0141         if (rhs.userType() == qMetaTypeId<int>()) {
0142             equal = (lhs.value<MetaEnumVariable>() == rhs.value<int>());
0143         }
0144     } else {
0145         equal = (lhs == rhs);
0146     }
0147     return equal;
0148 }
0149 
0150 std::pair<qreal, QString> KTextTemplate::calcFileSize(qreal size, int unitSystem, qreal multiplier)
0151 {
0152     std::pair<qreal, QString> ret;
0153 
0154     int _unitSystem = unitSystem;
0155 
0156     if ((_unitSystem != 2) && (_unitSystem != 10)) {
0157         qWarning("%s",
0158                  "Unrecognized file size unit system. Falling back to "
0159                  "decimal unit system.");
0160         _unitSystem = 10;
0161     }
0162 
0163     if (size == 0.0) {
0164         ret.first = 0.0;
0165         ret.second = QStringLiteral("bytes");
0166         return ret;
0167     }
0168     if ((size == 1.0) || (size == -1.0)) {
0169         ret.first = 1.0;
0170         ret.second = QStringLiteral("byte");
0171         return ret;
0172     }
0173 
0174     qreal _size = size * multiplier;
0175 
0176     const bool positiveValue = (_size > 0);
0177 
0178     if (!positiveValue) {
0179         _size *= -1;
0180     }
0181 
0182     static const QStringList binaryUnits({QStringLiteral("bytes"),
0183                                           QStringLiteral("KiB"),
0184                                           QStringLiteral("MiB"),
0185                                           QStringLiteral("GiB"),
0186                                           QStringLiteral("TiB"),
0187                                           QStringLiteral("PiB"),
0188                                           QStringLiteral("EiB"),
0189                                           QStringLiteral("ZiB"),
0190                                           QStringLiteral("YiB")});
0191 
0192     static const QStringList decimalUnits({QStringLiteral("bytes"),
0193                                            QStringLiteral("KB"),
0194                                            QStringLiteral("MB"),
0195                                            QStringLiteral("GB"),
0196                                            QStringLiteral("TB"),
0197                                            QStringLiteral("PB"),
0198                                            QStringLiteral("EB"),
0199                                            QStringLiteral("ZB"),
0200                                            QStringLiteral("YB")});
0201 
0202     bool found = false;
0203     int count = 0;
0204     const qreal baseVal = (_unitSystem == 10) ? 1000.0F : 1024.0F;
0205     qreal current = 1.0F;
0206     int units = decimalUnits.size();
0207     while (!found && (count < units)) {
0208         current *= baseVal;
0209         if (_size < current) {
0210             found = true;
0211             break;
0212         }
0213         count++;
0214     }
0215 
0216     if (count >= units) {
0217         count = (units - 1);
0218     }
0219 
0220     qreal devider = current / baseVal;
0221     _size = _size / devider;
0222 
0223     if (!positiveValue) {
0224         _size *= -1.0;
0225     }
0226 
0227     ret.first = _size;
0228     ret.second = (_unitSystem == 10) ? decimalUnits.at(count) : binaryUnits.at(count);
0229 
0230     return ret;
0231 }
0232 
0233 KTextTemplate::SafeString KTextTemplate::toString(const QVariantList &list)
0234 {
0235     QString output(QLatin1Char('['));
0236     auto it = list.constBegin();
0237     const auto end = list.constEnd();
0238     while (it != end) {
0239         const auto item = *it;
0240         if (isSafeString(item)) {
0241             output += QStringLiteral("u\'") + static_cast<QString>(getSafeString(item).get()) + QLatin1Char('\'');
0242         }
0243         if ((item.userType() == qMetaTypeId<int>()) || (item.userType() == qMetaTypeId<uint>()) || (item.userType() == qMetaTypeId<double>())
0244             || (item.userType() == qMetaTypeId<float>()) || (item.userType() == qMetaTypeId<long long>())
0245             || (item.userType() == qMetaTypeId<unsigned long long>())) {
0246             output += item.value<QString>();
0247         }
0248         if (item.userType() == qMetaTypeId<QVariantList>()) {
0249             output += static_cast<QString>(toString(item.value<QVariantList>()).get());
0250         }
0251         if ((it + 1) != end)
0252             output += QStringLiteral(", ");
0253         ++it;
0254     }
0255 
0256     return output.append(QLatin1Char(']'));
0257 }