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 }