File indexing completed on 2024-06-23 05:49:02

0001 /*
0002     This file is part of the Okteta Kasten Framework, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2012 Alex Richardson <alex.richardson@gmx.de>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #ifndef KASTEN_PARSERUTILS_HPP
0010 #define KASTEN_PARSERUTILS_HPP
0011 
0012 #include <QDebug>
0013 #include <QStringList>
0014 #include <KLocalizedString>
0015 
0016 #include "../datatypes/datainformation.hpp"
0017 #include "../datatypes/strings/stringdatainformation.hpp"
0018 #include "../script/scriptlogger.hpp"
0019 
0020 // forward declare so I don't have to repeat in all the parsers
0021 class ArrayDataInformation;
0022 class PrimitiveDataInformation;
0023 class AbstractBitfieldDataInformation;
0024 class StructureDataInformation;
0025 class UnionDataInformation;
0026 class EnumDataInformation;
0027 class StringDataInformation;
0028 class TaggedUnionDataInformation;
0029 class PointerDataInformation;
0030 
0031 class QScriptValue;
0032 class QScriptEngine;
0033 
0034 /** For use by the parsers so that the functions don't have as many parameters */
0035 struct ParserInfo
0036 {
0037     inline ParserInfo(const QString& name, ScriptLogger* logger, DataInformation* parent, QScriptEngine* engine)
0038         : name(name)
0039         , logger(logger)
0040         , parent(parent)
0041         , engine(engine)
0042     {
0043         Q_CHECK_PTR(logger);
0044     }
0045     inline ParserInfo(const ParserInfo& i) = default;
0046     inline ~ParserInfo() = default;
0047 
0048     QString name;
0049     ScriptLogger* logger;
0050     DataInformation* parent;
0051     QScriptEngine* engine;
0052 
0053     inline QString context() const
0054     {
0055         return parent ? parent->fullObjectPath() + QLatin1Char('.') + name : name;
0056     }
0057     inline QDebug info() const { return logger->info(context()); }
0058     inline QDebug warn() const { return logger->warn(context()); }
0059     inline QDebug error() const { return logger->error(context()); }
0060 };
0061 
0062 class ChildrenParser
0063 {
0064 public:
0065     virtual ~ChildrenParser() = default;
0066 
0067     virtual DataInformation* next() = 0;
0068     virtual bool hasNext() = 0;
0069     virtual void setParent(DataInformation* parent) = 0;
0070 };
0071 
0072 /**
0073  * Holds a number that was converted either from a QScriptValue or a QString
0074  */
0075 template <typename T>
0076 struct ParsedNumber
0077 {
0078     ParsedNumber() = default;
0079     ParsedNumber(T val, const QString& str, bool ok)
0080         : string(str)
0081         , value(val)
0082         , isValid(ok)
0083     {}
0084 
0085     QString string;
0086     T value = 0;
0087     bool isValid = false;
0088 
0089     static ParsedNumber<T> badInput(const QString& str) { return ParsedNumber<T>(T(), str, false); }
0090     inline bool isError() { return !isValid && !string.isEmpty(); }
0091     inline bool isEmpty() { Q_ASSERT(!isValid); return string.isEmpty(); }
0092 };
0093 
0094 namespace ParserStrings {
0095 
0096 QString TYPE_ARRAY();
0097 QString TYPE_BITFIELD();
0098 QString TYPE_ENUM();
0099 QString TYPE_FLAGS();
0100 QString TYPE_PRIMITIVE();
0101 QString TYPE_STRING();
0102 QString TYPE_STRUCT();
0103 QString TYPE_UNION();
0104 QString TYPE_POINTER();
0105 QString TYPE_TAGGED_UNION();
0106 /** Only needed for .osd */
0107 QString TYPE_ENUMDEF();
0108 QString TYPE_ALTERNATIVES();
0109 QString TYPE_GROUP();
0110 
0111 // lock offset
0112 QString PROPERTY_DEFAULT_LOCK_OFFSET();
0113 // all types
0114 QString PROPERTY_NAME();
0115 QString PROPERTY_BYTEORDER();
0116 QString PROPERTY_PARENT();
0117 QString PROPERTY_VALIDATION_ERROR();
0118 QString PROPERTY_VALID();
0119 QString PROPERTY_ABLE_TO_READ();
0120 QString PROPERTY_UPDATE_FUNC();
0121 QString PROPERTY_VALIDATION_FUNC();
0122 QString PROPERTY_TO_STRING_FUNC();
0123 QString PROPERTY_DATATYPE();
0124 QString PROPERTY_CUSTOM_TYPE_NAME();
0125 // enum
0126 QString PROPERTY_ENUM_VALUES();
0127 // this one is javascript only
0128 QString PROPERTY_ENUM_NAME();
0129 // array/bitfield
0130 QString PROPERTY_TYPE();
0131 // array
0132 QString PROPERTY_LENGTH();
0133 // bitfield
0134 QString PROPERTY_WIDTH();
0135 // struct/union
0136 QString PROPERTY_CHILDREN();
0137 QString PROPERTY_CHILD_COUNT();
0138 QString PROPERTY_CHILD();
0139 // strings
0140 QString PROPERTY_CHAR_COUNT();
0141 QString PROPERTY_BYTE_COUNT();
0142 QString PROPERTY_MAX_CHAR_COUNT();
0143 QString PROPERTY_MAX_BYTE_COUNT();
0144 QString PROPERTY_TERMINATED_BY();
0145 QString PROPERTY_ENCODING();
0146 // primitive
0147 QString PROPERTY_VALUE();
0148 // pointer
0149 QString PROPERTY_TARGET();
0150 QString PROPERTY_SCALE();
0151 QString PROPERTY_INTERPRET_FUNC();
0152 // tagged union
0153 QString PROPERTY_ALTERNATIVES();
0154 QString PROPERTY_DEFAULT_CHILDREN();
0155 QString PROPERTY_SELECT_IF();
0156 QString PROPERTY_STRUCT_NAME();
0157 
0158 QString PROPERTY_INTERNAL_TYPE();
0159 
0160 QStringList ALL_PROPERTIES();
0161 
0162 QString NAME_POINTER_VALUE_TYPE();
0163 QString NAME_POINTER_TARGET();
0164 QString NAME_ARRAY_TYPE();
0165 
0166 }
0167 
0168 namespace ParserUtils {
0169 
0170 /** If string starts with 0x, the remainder is interpreted as a hexadecimal (unsigned) number
0171  * otherwise it will be parsed as a decimal number
0172  * @param str the string to convert
0173  * @return a parsed number (check the isValid member to see if conversion succeeded)
0174  */
0175 ParsedNumber<int> intFromString(const QString& str);
0176 /** @see ParserUtils::intFromString() */
0177 ParsedNumber<uint> uintFromString(const QString& str);
0178 /** @see ParserUtils::intFromString() */
0179 ParsedNumber<quint64> uint64FromString(const QString& str);
0180 /** Checks whether the value is a number, and if it is converts it.
0181  * Since all script values use double internally, a valid number can be out of bounds, too
0182  * @param val the value to convert
0183  * @see ParserUtils::intFromString()
0184  */
0185 ParsedNumber<int> intFromScriptValue(const QScriptValue& val);
0186 /** @see ParserUtils::intFromScriptValue() */
0187 ParsedNumber<uint> uintFromScriptValue(const QScriptValue& val);
0188 /** @see ParserUtils::intFromScriptValue() */
0189 ParsedNumber<quint64> uint64FromScriptValue(const QScriptValue& val);
0190 
0191 DataInformation::DataInformationEndianess byteOrderFromString(const QString& string, const LoggerWithContext& logger);
0192 QString byteOrderToString(DataInformation::DataInformationEndianess order);
0193 
0194 StringDataInformation::StringType toStringEncoding(const QString& str, const LoggerWithContext& logger);
0195 
0196 /** This essentially calls engine->evaluate(str), but ensures it can be a function (QTBUG-5757)  */
0197 QScriptValue functionSafeEval(QScriptEngine* engine, const QString& str);
0198 
0199 }
0200 
0201 #endif /* KASTEN_PARSERUTILS_HPP */