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

0001 /*
0002   This file is part of the KTextTemplate library
0003 
0004   SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
0005 
0006   SPDX-License-Identifier: LGPL-2.1-or-later
0007 
0008 */
0009 
0010 #include "typeaccessor.h"
0011 
0012 #include "metaenumvariable_p.h"
0013 #include "safestring.h"
0014 
0015 #include <QRegularExpression>
0016 #include <QStringList>
0017 #include <QVariant>
0018 
0019 namespace KTextTemplate
0020 {
0021 
0022 static QRegularExpression getIsTitleRE()
0023 {
0024     QRegularExpression titleRe(QStringLiteral("\\b[a-z]"), QRegularExpression::InvertedGreedinessOption);
0025     return titleRe;
0026 }
0027 
0028 static QRegularExpression getTitleRE()
0029 {
0030     QRegularExpression titleRe(QStringLiteral("\\b(.)"), QRegularExpression::InvertedGreedinessOption);
0031     return titleRe;
0032 }
0033 
0034 template<>
0035 QVariant TypeAccessor<KTextTemplate::SafeString &>::lookUp(const KTextTemplate::SafeString &object, const QString &property)
0036 {
0037     if (property == QStringLiteral("capitalize")) {
0038         const QString &s = object.get();
0039         return {s.at(0).toUpper() + s.right(s.length() - 1)};
0040     }
0041 
0042     static const QLatin1String falseString("False");
0043     static const QLatin1String trueString("True");
0044 
0045     if (property == QStringLiteral("isalnum")) {
0046         const QString &s = object.get();
0047         auto it = s.constBegin();
0048         while (it != s.constEnd()) {
0049             if (!it->isLetterOrNumber())
0050                 return falseString;
0051             ++it;
0052         }
0053         return trueString;
0054     }
0055     if (property == QStringLiteral("isalpha")) {
0056         const QString &s = object.get();
0057         auto it = s.constBegin();
0058         if (it == s.constEnd())
0059             return falseString;
0060         while (it != s.constEnd()) {
0061             if (!it->isLetter())
0062                 return falseString;
0063             ++it;
0064         }
0065         return trueString;
0066     }
0067     if (property == QStringLiteral("isdigit")) {
0068         const QString &s = object.get();
0069         auto it = s.constBegin();
0070         while (it != s.constEnd()) {
0071             if (!it->isNumber())
0072                 return falseString;
0073             ++it;
0074         }
0075         return trueString;
0076     }
0077     if (property == QStringLiteral("islower")) {
0078         const QString s = object.get().toLower();
0079         return (s == object.get()) ? trueString : falseString;
0080     }
0081     if (property == QStringLiteral("isspace")) {
0082         const QString s = object.get().trimmed();
0083         return (s.isEmpty()) ? trueString : falseString;
0084     }
0085     if (property == QStringLiteral("istitle")) {
0086         const QString &s = object.get();
0087 
0088         static const auto titleRe = getIsTitleRE();
0089         return (titleRe.match(s).hasMatch()) ? falseString : trueString;
0090     }
0091     if (property == QStringLiteral("isupper")) {
0092         const QString s = object.get().toUpper();
0093         return (s == object) ? trueString : falseString;
0094     }
0095     if (property == QStringLiteral("lower")) {
0096         return object.get().toLower();
0097     }
0098     if (property == QStringLiteral("splitlines")) {
0099         const auto strings = object.get().split(QLatin1Char('\n'));
0100         QVariantList list;
0101         auto it = strings.constBegin();
0102         const auto end = strings.constEnd();
0103         for (; it != end; ++it)
0104             list << *it;
0105         return list;
0106     }
0107     if (property == QStringLiteral("strip")) {
0108         return object.get().trimmed();
0109     }
0110     if (property == QStringLiteral("swapcase")) {
0111         const QString &inputString = object.get();
0112         QString s;
0113         s.reserve(inputString.size());
0114         auto it = inputString.constBegin();
0115         while (it != inputString.constEnd()) {
0116             if (it->isUpper())
0117                 s += it->toLower();
0118             else if (it->isLower())
0119                 s += it->toUpper();
0120             else
0121                 s += *it;
0122             ++it;
0123         }
0124         return s;
0125     }
0126     if (property == QStringLiteral("title")) {
0127         static const auto titleRe = getTitleRE();
0128 
0129         const QString &s = object.get();
0130         QString output;
0131         output.reserve(s.size());
0132         auto pos = 0;
0133         auto nextPos = 0;
0134         int matchedLength;
0135 
0136         auto it = titleRe.globalMatch(s);
0137         while (it.hasNext()) {
0138             auto match = it.next();
0139             pos = match.capturedStart();
0140             output += match.captured().toUpper();
0141             matchedLength = match.capturedLength();
0142             if (it.hasNext()) {
0143                 match = it.peekNext();
0144                 nextPos = match.capturedStart();
0145                 output += s.mid(pos + matchedLength, nextPos - pos - 1);
0146             } else {
0147                 output += s.right(s.length() - (pos + matchedLength));
0148             }
0149         }
0150 
0151         return output;
0152     }
0153     if (property == QStringLiteral("upper")) {
0154         return object.get().toUpper();
0155     }
0156     return {};
0157 }
0158 
0159 template<>
0160 QVariant TypeAccessor<MetaEnumVariable &>::lookUp(const MetaEnumVariable &object, const QString &property)
0161 {
0162     if (property == QStringLiteral("name"))
0163         return QLatin1String(object.enumerator.name());
0164     if (property == QStringLiteral("value"))
0165         return object.value;
0166     if (property == QStringLiteral("key"))
0167         return QLatin1String(object.enumerator.valueToKey(object.value));
0168     if (property == QStringLiteral("scope"))
0169         return QLatin1String(object.enumerator.scope());
0170     if (property == QStringLiteral("keyCount"))
0171         return object.enumerator.keyCount();
0172 
0173     auto ok = false;
0174     const auto listIndex = property.toInt(&ok);
0175     if (ok) {
0176         if (listIndex >= object.enumerator.keyCount())
0177             return {};
0178 
0179         const MetaEnumVariable mev(object.enumerator, object.enumerator.value(listIndex));
0180         return QVariant::fromValue(mev);
0181     }
0182 
0183     return {};
0184 }
0185 }