File indexing completed on 2024-06-30 05:51:31
0001 /* 0002 This file is part of the Okteta Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2011, 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 #include "primitivescriptclass.hpp" 0010 #include "../../datatypes/primitive/primitivedatainformation.hpp" 0011 #include "../../parsers/parserutils.hpp" 0012 #include "../../allprimitivetypes.hpp" 0013 #include <structureslogging.hpp> 0014 0015 PrimitiveScriptClass::PrimitiveScriptClass(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo) 0016 : DefaultScriptClass(engine, handlerInfo) 0017 { 0018 mIterableProperties.reserve(mIterableProperties.size() + 20); 0019 s_value = engine->toStringHandle(QStringLiteral("value")); 0020 mIterableProperties.append(qMakePair(s_value, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0021 s_type = engine->toStringHandle(QStringLiteral("type")); 0022 mIterableProperties.append(qMakePair(s_type, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0023 0024 s_bool = engine->toStringHandle(QStringLiteral("bool")); 0025 mIterableProperties.append(qMakePair(s_bool, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0026 s_char = engine->toStringHandle(QStringLiteral("char")); 0027 mIterableProperties.append(qMakePair(s_char, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0028 s_double = engine->toStringHandle(QStringLiteral("double")); 0029 mIterableProperties.append(qMakePair(s_double, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0030 s_float = engine->toStringHandle(QStringLiteral("float")); 0031 mIterableProperties.append(qMakePair(s_float, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0032 s_int = engine->toStringHandle(QStringLiteral("int")); 0033 mIterableProperties.append(qMakePair(s_int, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0034 s_int8 = engine->toStringHandle(QStringLiteral("int8")); 0035 mIterableProperties.append(qMakePair(s_int8, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0036 s_int16 = engine->toStringHandle(QStringLiteral("int16")); 0037 mIterableProperties.append(qMakePair(s_int16, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0038 s_int32 = engine->toStringHandle(QStringLiteral("int32")); 0039 mIterableProperties.append(qMakePair(s_int32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0040 s_int64low32 = engine->toStringHandle(QStringLiteral("int64low32")); 0041 mIterableProperties.append(qMakePair(s_int64low32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0042 s_int64high32 = engine->toStringHandle(QStringLiteral("int64high32")); 0043 mIterableProperties.append(qMakePair(s_int64high32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0044 s_int64 = engine->toStringHandle(QStringLiteral("int64")); 0045 mIterableProperties.append(qMakePair(s_int64, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0046 s_uint = engine->toStringHandle(QStringLiteral("uint")); 0047 mIterableProperties.append(qMakePair(s_uint, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0048 s_uint8 = engine->toStringHandle(QStringLiteral("uint8")); 0049 mIterableProperties.append(qMakePair(s_uint8, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0050 s_uint16 = engine->toStringHandle(QStringLiteral("uint16")); 0051 mIterableProperties.append(qMakePair(s_uint16, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0052 s_uint32 = engine->toStringHandle(QStringLiteral("uint32")); 0053 mIterableProperties.append(qMakePair(s_uint32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0054 s_uint64low32 = engine->toStringHandle(QStringLiteral("uint64low32")); 0055 mIterableProperties.append(qMakePair(s_uint64low32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0056 s_uint64high32 = engine->toStringHandle(QStringLiteral("uint64high32")); 0057 mIterableProperties.append(qMakePair(s_uint64high32, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0058 s_uint64 = engine->toStringHandle(QStringLiteral("uint64")); 0059 mIterableProperties.append(qMakePair(s_uint64, QScriptValue::ReadOnly | QScriptValue::Undeletable)); 0060 0061 mPrimitivePrototype = engine->newObject(); 0062 mPrimitivePrototype.setProperty(QStringLiteral("toString"), engine->newFunction(Primitive_proto_toString)); 0063 } 0064 0065 PrimitiveScriptClass::~PrimitiveScriptClass() = default; 0066 0067 bool PrimitiveScriptClass::queryAdditionalProperty(const DataInformation* data, const QScriptString& name, QScriptClass::QueryFlags* flags, uint*) 0068 { 0069 Q_UNUSED(data) 0070 // TODO assign ids to improve speed? cant have children, so it won't conflict 0071 // no need to modify flags since both read and write are handled 0072 if (name == s_value || name == s_type) { 0073 *flags &= ~HandlesWriteAccess; 0074 return true; 0075 } 0076 if (name == s_bool || name == s_char || name == s_int || name == s_uint || name == s_float 0077 || name == s_double || name == s_int64 || name == s_uint64 || name == s_int64low32 0078 || name == s_int64high32 || name == s_uint64low32 || name == s_uint64high32 || name == s_int8 0079 || name == s_int16 || name == s_int32 || name == s_uint8 || name == s_uint16 || name == s_uint32) { 0080 *flags &= ~HandlesWriteAccess; 0081 return true; 0082 } 0083 return false; 0084 } 0085 0086 bool PrimitiveScriptClass::additionalPropertyFlags(const DataInformation*, const QScriptString&, uint, QScriptValue::PropertyFlags*) 0087 { 0088 return false; 0089 } 0090 0091 QScriptValue PrimitiveScriptClass::additionalProperty(const DataInformation* data, const QScriptString& name, uint) 0092 { 0093 const PrimitiveDataInformation* pData = data->asPrimitive(); 0094 0095 if (name == s_value) { 0096 if (pData->wasAbleToRead()) { 0097 return pData->valueAsQScriptValue(); 0098 } 0099 QScriptValue callee = engine()->currentContext()->thisObject(); 0100 DataInformation* cause = toDataInformation(callee); 0101 if (cause) { 0102 pData->logError() << "Attempting to read from uninitialized value. Callee was " << cause->fullObjectPath(); 0103 } else { 0104 pData->logError() << "Attempting to read from uninitialized value. Callee could not be determined"; 0105 } 0106 return engine()->undefinedValue(); 0107 } 0108 if (name == s_type) { 0109 // bitfields are handled by own scriptclass and NotPrimitive indicates an error 0110 Q_ASSERT(!pData->isBitfield()); 0111 Q_ASSERT(pData->type() != PrimitiveDataType::Invalid); 0112 return PrimitiveType::standardTypeName(pData->type()); 0113 } 0114 0115 AllPrimitiveTypes value = pData->value(); 0116 if (name == s_bool) { 0117 return value.value<quint64>() != 0; 0118 } 0119 if (name == s_char) { 0120 return QString(value.value<quint8>() > 127 ? QChar::ReplacementCharacter : QChar(value.value<qint8>(), 0)); 0121 } 0122 if (name == s_float) { 0123 return value.value<float>(); 0124 } 0125 if (name == s_double) { 0126 return value.value<double>(); 0127 } 0128 if (name == s_int || name == s_int32 || name == s_int64low32) { 0129 return value.value<qint32>(); 0130 } 0131 if (name == s_uint || name == s_uint32 || name == s_uint64low32) { 0132 return value.value<quint32>(); 0133 } 0134 if (name == s_int64) { 0135 return QString::number(value.value<qint64>()); 0136 } 0137 if (name == s_uint64) { 0138 return QString::number(value.value<quint64>()); 0139 } 0140 if (name == s_int64high32) { 0141 return qint32(value.value<qint64>() >> 32); 0142 } 0143 if (name == s_uint64high32) { 0144 return quint32(value.value<quint64>() >> 32); 0145 } 0146 if (name == s_int8) { 0147 return qint32(value.value<qint8>()); 0148 } 0149 if (name == s_int16) { 0150 return qint32(value.value<qint16>()); 0151 } 0152 if (name == s_uint8) { 0153 return quint32(value.value<quint8>()); 0154 } 0155 if (name == s_uint16) { 0156 return quint32(value.value<quint16>()); 0157 } 0158 0159 return {}; 0160 } 0161 0162 bool PrimitiveScriptClass::setAdditionalProperty(DataInformation* data, const QScriptString& name, uint, const QScriptValue& value) 0163 { 0164 Q_UNUSED(value); 0165 Q_UNUSED(data); 0166 Q_UNUSED(name); 0167 // TODO allow changing type 0168 return false; 0169 } 0170 0171 QScriptValue PrimitiveScriptClass::prototype() const 0172 { 0173 return mPrimitivePrototype; 0174 } 0175 0176 QScriptValue PrimitiveScriptClass::Primitive_proto_toString(QScriptContext* ctx, QScriptEngine* eng) 0177 { 0178 DataInformation* data = toDataInformation(ctx->thisObject()); 0179 if (!data) { 0180 qCWarning(LOG_KASTEN_OKTETA_CONTROLLERS_STRUCTURES) << "could not cast data"; 0181 return eng->undefinedValue(); 0182 } 0183 // this might allow proper comparison between values without having to call .value 0184 return data->wasAbleToRead() ? data->valueString() : eng->undefinedValue(); 0185 }