File indexing completed on 2025-01-05 05:23:44
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 SPDX-FileCopyrightText: 2016 Aaron Bishop <erroneous@gmail.com> 0006 0007 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0008 */ 0009 0010 #include "parserutils.hpp" 0011 0012 #include <QScriptValue> 0013 #include <QScriptEngine> 0014 0015 namespace ParserStrings { 0016 0017 QString TYPE_ARRAY() { return QStringLiteral("array"); } 0018 QString TYPE_BITFIELD() { return QStringLiteral("bitfield"); } 0019 QString TYPE_ENUM() { return QStringLiteral("enum"); } 0020 QString TYPE_FLAGS() { return QStringLiteral("flags"); } 0021 QString TYPE_PRIMITIVE() { return QStringLiteral("primitive"); } 0022 QString TYPE_STRING() { return QStringLiteral("string"); } 0023 QString TYPE_STRUCT() { return QStringLiteral("struct"); } 0024 QString TYPE_UNION() { return QStringLiteral("union"); } 0025 QString TYPE_POINTER() { return QStringLiteral("pointer"); } 0026 QString TYPE_TAGGED_UNION() { return QStringLiteral("taggedUnion"); } 0027 0028 QString TYPE_ENUMDEF() { return QStringLiteral("enumDef"); } 0029 QString TYPE_ALTERNATIVES() { return QStringLiteral("alternatives"); } 0030 QString TYPE_GROUP() { return QStringLiteral("group"); } 0031 0032 QString PROPERTY_DEFAULT_LOCK_OFFSET() { return QStringLiteral("defaultLockOffset"); } 0033 0034 QString PROPERTY_NAME() { return QStringLiteral("name"); } 0035 QString PROPERTY_BYTEORDER() { return QStringLiteral("byteOrder"); } 0036 QString PROPERTY_PARENT() { return QStringLiteral("parent"); } 0037 QString PROPERTY_VALIDATION_ERROR() { return QStringLiteral("validationError"); } 0038 QString PROPERTY_VALID() { return QStringLiteral("valid"); } 0039 QString PROPERTY_ABLE_TO_READ() { return QStringLiteral("wasAbleToRead"); } 0040 QString PROPERTY_UPDATE_FUNC() { return QStringLiteral("updateFunc"); } 0041 QString PROPERTY_VALIDATION_FUNC() { return QStringLiteral("validationFunc"); } 0042 QString PROPERTY_TO_STRING_FUNC() { return QStringLiteral("toStringFunc"); } 0043 QString PROPERTY_DATATYPE() { return QStringLiteral("datatype"); } 0044 QString PROPERTY_CUSTOM_TYPE_NAME() { return QStringLiteral("typeName"); } 0045 0046 QString PROPERTY_ENUM_VALUES() { return QStringLiteral("enumValues"); } 0047 0048 QString PROPERTY_ENUM_NAME() { return QStringLiteral("enumName"); } 0049 0050 QString PROPERTY_TYPE() { return QStringLiteral("type"); } 0051 0052 QString PROPERTY_LENGTH() { return QStringLiteral("length"); } 0053 0054 QString PROPERTY_WIDTH() { return QStringLiteral("width"); } 0055 QString PROPERTY_CHILDREN() { return QStringLiteral("fields"); } 0056 QString PROPERTY_CHILD_COUNT() { return QStringLiteral("childCount"); } 0057 QString PROPERTY_CHILD() { return QStringLiteral("child"); } 0058 0059 QString PROPERTY_CHAR_COUNT() { return QStringLiteral("charCount"); } 0060 QString PROPERTY_BYTE_COUNT() { return QStringLiteral("byteCount"); } 0061 QString PROPERTY_MAX_CHAR_COUNT() { return QStringLiteral("maxCharCount"); } 0062 QString PROPERTY_MAX_BYTE_COUNT() { return QStringLiteral("maxByteCount"); } 0063 QString PROPERTY_TERMINATED_BY() { return QStringLiteral("terminatedBy"); } 0064 QString PROPERTY_ENCODING() { return QStringLiteral("encoding"); } 0065 // primitive 0066 QString PROPERTY_VALUE() { return QStringLiteral("value"); } 0067 // pointer 0068 QString PROPERTY_TARGET() { return QStringLiteral("target"); } 0069 QString PROPERTY_SCALE() { return QStringLiteral("scale"); } 0070 QString PROPERTY_INTERPRET_FUNC() { return QStringLiteral("interpretFunc"); } 0071 // tagged union 0072 QString PROPERTY_ALTERNATIVES() { return QStringLiteral("alternatives"); } 0073 QString PROPERTY_DEFAULT_CHILDREN() { return QStringLiteral("defaultFields"); } 0074 QString PROPERTY_SELECT_IF() { return QStringLiteral("selectIf"); } 0075 QString PROPERTY_STRUCT_NAME() { return QStringLiteral("structName"); } 0076 0077 QString PROPERTY_INTERNAL_TYPE() { return QStringLiteral("__type"); } 0078 0079 QStringList ALL_PROPERTIES() 0080 { 0081 return QStringList { 0082 PROPERTY_ABLE_TO_READ(), 0083 PROPERTY_ALTERNATIVES(), 0084 PROPERTY_BYTEORDER(), 0085 PROPERTY_BYTE_COUNT(), 0086 PROPERTY_CHAR_COUNT(), 0087 PROPERTY_CHAR_COUNT(), 0088 PROPERTY_CHILD(), 0089 PROPERTY_CHILDREN(), 0090 PROPERTY_CHILD_COUNT(), 0091 PROPERTY_DATATYPE(), 0092 PROPERTY_DEFAULT_CHILDREN(), 0093 PROPERTY_ENCODING(), 0094 PROPERTY_ENUM_NAME(), 0095 PROPERTY_ENUM_VALUES(), 0096 PROPERTY_INTERNAL_TYPE(), 0097 PROPERTY_INTERPRET_FUNC(), 0098 PROPERTY_LENGTH(), 0099 PROPERTY_MAX_BYTE_COUNT(), 0100 PROPERTY_MAX_CHAR_COUNT(), 0101 PROPERTY_NAME(), 0102 PROPERTY_PARENT(), 0103 PROPERTY_SCALE(), 0104 PROPERTY_SELECT_IF(), 0105 PROPERTY_STRUCT_NAME(), 0106 PROPERTY_TARGET(), 0107 PROPERTY_TERMINATED_BY(), 0108 PROPERTY_TYPE(), 0109 PROPERTY_UPDATE_FUNC(), 0110 PROPERTY_VALID(), 0111 PROPERTY_VALIDATION_ERROR(), 0112 PROPERTY_VALIDATION_FUNC(), 0113 PROPERTY_VALUE(), 0114 PROPERTY_WIDTH() 0115 }; 0116 } 0117 0118 QString NAME_POINTER_VALUE_TYPE() { return QStringLiteral("<pointer value type>"); } 0119 QString NAME_POINTER_TARGET() { return QStringLiteral("<pointer target>"); } 0120 QString NAME_ARRAY_TYPE() { return QStringLiteral("<array type>"); } 0121 } 0122 0123 ParsedNumber<int> ParserUtils::intFromString(const QString& str) 0124 { 0125 int value = 0; 0126 bool okay = false; 0127 if (str.startsWith(QLatin1String("0x"))) { 0128 value = str.midRef(2).toInt(&okay, 16); 0129 } else if (str.startsWith(QLatin1String("-0x"))) { 0130 // special case for minimum possible value 0131 if (str == QLatin1String("-0x80000000")) { 0132 return ParsedNumber<int>(-0x80000000, str, true); 0133 } 0134 value = -str.midRef(3).toInt(&okay, 16); 0135 } else { 0136 value = str.toInt(&okay, 10); 0137 } 0138 return ParsedNumber<int>(value, str, okay); 0139 } 0140 0141 ParsedNumber<uint> ParserUtils::uintFromString(const QString& str) 0142 { 0143 uint value = 0; 0144 bool okay; 0145 if (str.startsWith(QLatin1String("0x"))) { 0146 value = str.midRef(2).toUInt(&okay, 16); 0147 } else { 0148 value = str.toUInt(&okay, 10); 0149 } 0150 return ParsedNumber<uint>(value, str, okay); 0151 } 0152 0153 ParsedNumber<quint64> ParserUtils::uint64FromString(const QString& str) 0154 { 0155 quint64 value = 0; 0156 bool okay; 0157 if (str.startsWith(QLatin1String("0x"))) { 0158 value = str.midRef(2).toULongLong(&okay, 16); 0159 } else { 0160 value = str.toULongLong(&okay, 10); 0161 } 0162 return ParsedNumber<quint64>(value, str, okay); 0163 } 0164 0165 DataInformation::DataInformationEndianess ParserUtils::byteOrderFromString(const QString& string, 0166 const LoggerWithContext& logger) 0167 { 0168 const QString lower = string.toLower(); 0169 if (lower == QLatin1String("bigendian") || lower == QLatin1String("big-endian")) { 0170 return DataInformation::DataInformationEndianess::EndianessBig; 0171 } 0172 if (lower == QLatin1String("littleendian") || lower == QLatin1String("little-endian")) { 0173 return DataInformation::DataInformationEndianess::EndianessLittle; 0174 } 0175 if (lower == QLatin1String("fromsettings") || lower == QLatin1String("from-settings")) { 0176 return DataInformation::DataInformationEndianess::EndianessFromSettings; 0177 } 0178 if (lower == QLatin1String("inherit")) { 0179 return DataInformation::DataInformationEndianess::EndianessInherit; 0180 } 0181 0182 logger.warn().nospace() << "Unrecognized byte order '" << string << "', defaulting to 'inherit'"; 0183 return DataInformation::DataInformationEndianess::EndianessInherit; 0184 } 0185 0186 ParsedNumber<int> ParserUtils::intFromScriptValue(const QScriptValue& val) 0187 { 0188 if (val.isNumber()) { 0189 // check whether it is in range 0190 const qsreal doubleVal = val.toNumber(); 0191 const int value = val.toInt32(); 0192 if (doubleVal != qsreal(value)) { 0193 return ParsedNumber<int>::badInput(val.toString()); 0194 } 0195 return ParsedNumber<int>(value, val.toString(), true); 0196 } 0197 if (val.isString()) { 0198 return intFromString(val.toString()); 0199 } 0200 return ParsedNumber<int>::badInput(val.toString()); 0201 } 0202 0203 ParsedNumber<uint> ParserUtils::uintFromScriptValue(const QScriptValue& val) 0204 { 0205 if (val.isNumber()) { 0206 // check whether it is in range 0207 const uint value = val.toUInt32(); 0208 const qsreal doubleVal = val.toNumber(); 0209 if (doubleVal != qsreal(value)) { 0210 return ParsedNumber<uint>::badInput(val.toString()); 0211 } 0212 return ParsedNumber<uint>(value, val.toString(), true); 0213 } 0214 if (val.isString()) { 0215 return uintFromString(val.toString()); 0216 } 0217 return ParsedNumber<uint>::badInput(val.toString()); 0218 } 0219 0220 ParsedNumber<quint64> ParserUtils::uint64FromScriptValue(const QScriptValue& val) 0221 { 0222 if (val.isNumber()) { 0223 // check whether it is in range 0224 const uint value = val.toUInt32(); 0225 const qsreal doubleVal = val.toNumber(); 0226 if (doubleVal != qsreal(value)) { 0227 return ParsedNumber<quint64>::badInput(val.toString()); 0228 } 0229 return ParsedNumber<quint64>(value, val.toString(), true); 0230 } 0231 if (val.isString()) { 0232 return uint64FromString(val.toString()); 0233 } 0234 return ParsedNumber<quint64>::badInput(val.toString()); 0235 } 0236 0237 QString ParserUtils::byteOrderToString(DataInformation::DataInformationEndianess order) 0238 { 0239 if (order == DataInformation::DataInformationEndianess::EndianessLittle) { 0240 return QStringLiteral("littleEndian"); 0241 } 0242 if (order == DataInformation::DataInformationEndianess::EndianessBig) { 0243 return QStringLiteral("bigEndian"); 0244 } 0245 if (order == DataInformation::DataInformationEndianess::EndianessFromSettings) { 0246 return QStringLiteral("fromSettings"); 0247 } 0248 return QStringLiteral("inherit"); 0249 } 0250 0251 StringDataInformation::StringType ParserUtils::toStringEncoding(const QString& str, const LoggerWithContext& logger) 0252 { 0253 QString enc = str.toLower(); 0254 if (enc == QLatin1String("ascii")) { 0255 return StringDataInformation::StringType::ASCII; 0256 } 0257 if (enc == QLatin1String("ebcdic")) { 0258 return StringDataInformation::StringType::EBCDIC; 0259 } 0260 if (enc == QLatin1String("latin1") || enc == QLatin1String("latin-1")) { 0261 return StringDataInformation::StringType::Latin1; 0262 } 0263 if (enc.startsWith(QLatin1String("utf"))) { 0264 QStringRef ref = enc.midRef(3); 0265 if (ref.at(0) == QLatin1Char('-')) { 0266 ref = enc.midRef(4); // strip '-' 0267 } 0268 if (ref == QLatin1String("8")) { 0269 return StringDataInformation::StringType::UTF8; 0270 } 0271 0272 if (ref == QLatin1String("16") || ref == QLatin1String("16le") || ref == QLatin1String("16-le")) { 0273 return StringDataInformation::StringType::UTF16_LE; 0274 } 0275 if (ref == QLatin1String("16be") || ref == QLatin1String("16-be")) { 0276 return StringDataInformation::StringType::UTF16_BE; 0277 } 0278 if (ref == QLatin1String("32") || ref == QLatin1String("32le") || ref == QLatin1String("32-le")) { 0279 return StringDataInformation::StringType::UTF32_LE; 0280 } 0281 if (ref == QLatin1String("32be") || ref == QLatin1String("32-be")) { 0282 return StringDataInformation::StringType::UTF32_BE; 0283 } 0284 } 0285 logger.warn() << "Unrecognized string encoding: " << enc; 0286 return StringDataInformation::StringType::InvalidEncoding; 0287 } 0288 0289 QScriptValue ParserUtils::functionSafeEval(QScriptEngine* engine, const QString& str) 0290 { 0291 if (str.isEmpty()) { 0292 return {}; 0293 } 0294 // must wrap in parentheses, see https://bugreports.qt-project.org/browse/QTBUG-5757 0295 QScriptValue ret = engine->evaluate(QLatin1Char('(') + str + QLatin1Char(')')); 0296 if (!ret.isFunction()) { 0297 return {str}; 0298 } 0299 return ret; 0300 }