File indexing completed on 2024-06-02 06:03:11

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "addressvalidator.hpp"
0010 
0011 // lib
0012 #include <logging.hpp>
0013 // Okteta core
0014 #include <Okteta/ValueCodec>
0015 // KF
0016 #include <KLocalizedString>
0017 // Qt
0018 #include <QString>
0019 #include <QJSEngine>
0020 #include <QJSValue>
0021 
0022 namespace Okteta {
0023 
0024 AddressValidator::AddressValidator(QObject* parent, Coding codecId)
0025     : QValidator(parent)
0026     , mCodecId(InvalidCoding)
0027     , mValueCodec(nullptr)
0028 {
0029     setCodec(codecId);
0030 }
0031 
0032 AddressValidator::~AddressValidator()
0033 {
0034     delete mValueCodec;
0035 }
0036 
0037 void AddressValidator::setCodec(Coding codecId)
0038 {
0039     if (codecId == mCodecId) {
0040         return;
0041     }
0042 
0043     mCodecId = codecId;
0044 
0045     delete mValueCodec;
0046     mValueCodec = ValueCodec::createCodec((Okteta::ValueCoding)mCodecId);
0047 }
0048 
0049 const QRegularExpression AddressValidator::expressionRegex =
0050     QRegularExpression(QStringLiteral("\\A[0-9a-fx\\+/\\s\\-\\*]+\\Z"),
0051             QRegularExpression::CaseInsensitiveOption); // FIXME this is way too simple, only there to test
0052 
0053 QValidator::State AddressValidator::validate(QString& string, int& pos) const
0054 {
0055     Q_UNUSED(pos)
0056 
0057     State result = QValidator::Acceptable;
0058     if (mCodecId == ExpressionCoding) {
0059         string = string.trimmed();
0060         if (!expressionRegex.match(string).hasMatch()) {
0061             result = QValidator::Invalid;
0062         }
0063         // only prefix has been typed:
0064         if (string == QLatin1String("+")
0065             || string == QLatin1String("-")
0066             || string.endsWith(QLatin1Char('x'))) { // 0x at end
0067             result = QValidator::Intermediate;
0068         }
0069     } else {
0070         const int stringLength = string.length();
0071         for (int i = 0; i < stringLength; ++i) {
0072             const QChar c = string.at(i);
0073             if (!mValueCodec->isValidDigit(c.toLatin1()) && !c.isSpace()) {
0074                 result = QValidator::Invalid;
0075                 break;
0076             }
0077         }
0078     }
0079     if (string.isEmpty()) {
0080         result = QValidator::Intermediate;
0081     }
0082     return result;
0083 }
0084 
0085 Address AddressValidator::toAddress(const QString& string, AddressType* addressType) const
0086 {
0087     Address address;
0088 
0089     QString expression = string.trimmed();
0090 
0091     if (addressType) {
0092         const AddressType type =
0093             expression.startsWith(QLatin1Char('+')) ? RelativeForwards :
0094             expression.startsWith(QLatin1Char('-')) ? RelativeBackwards :
0095             /* else */                                AbsoluteAddress;
0096 
0097         if (type != AbsoluteAddress) {
0098             expression.remove(0, 1);
0099         }
0100 
0101         *addressType = type;
0102     }
0103 
0104     if (mCodecId == ExpressionCoding) {
0105         QJSEngine evaluator;
0106         QJSValue value = evaluator.evaluate(expression);
0107         address = value.toInt();
0108         qCDebug(LOG_KASTEN_OKTETA_GUI) << "expression " << expression << " evaluated to: " << address;
0109 
0110         if (value.isError()) {
0111             qCWarning(LOG_KASTEN_OKTETA_GUI) << "evaluation error: " << value.toString();
0112             if (addressType) {
0113                 *addressType = InvalidAddressType;
0114             }
0115         }
0116     } else {
0117         const int base = (mCodecId == HexadecimalCoding) ? 16 : (mCodecId == DecimalCoding) ? 10 : 8;
0118         address = expression.toInt(nullptr, base);
0119     }
0120 
0121     return address;
0122 }
0123 
0124 QString AddressValidator::toString(Address address, AddressType addressType) const
0125 {
0126     // ExpressionCoding just uses base 10 so no need to adjust this code
0127     const int base = (mCodecId == HexadecimalCoding) ? 16 : (mCodecId == DecimalCoding) ? 10 : 8;
0128 
0129     QString string = QString::number(address, base);
0130 
0131     if (addressType == RelativeForwards) {
0132         string.prepend(QLatin1Char('+'));
0133     } else if (addressType == RelativeBackwards) {
0134         string.prepend(QLatin1Char('-'));
0135     }
0136 
0137     return string;
0138 }
0139 
0140 }
0141 
0142 #include "moc_addressvalidator.cpp"