File indexing completed on 2024-06-30 05:51:30
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 "arrayscriptclass.hpp" 0010 #include "../../datatypes/array/arraydatainformation.hpp" 0011 #include "../../parsers/parserutils.hpp" 0012 #include "../../parsers/scriptvalueconverter.hpp" 0013 #include "../scriptlogger.hpp" 0014 #include <structureslogging.hpp> 0015 0016 ArrayScriptClass::ArrayScriptClass(QScriptEngine* engine, ScriptHandlerInfo* handlerInfo) 0017 : DefaultScriptClass(engine, handlerInfo) 0018 { 0019 s_length = engine->toStringHandle(ParserStrings::PROPERTY_LENGTH()); 0020 mIterableProperties.append(qMakePair(s_length, QScriptValue::PropertyFlags(QScriptValue::Undeletable))); 0021 s_childType = engine->toStringHandle(QStringLiteral("childType")); 0022 // the preferred property (the same as childType) 0023 s_type = engine->toStringHandle(ParserStrings::PROPERTY_TYPE()); 0024 mIterableProperties.append(qMakePair(s_type, QScriptValue::PropertyFlags(QScriptValue::Undeletable))); 0025 0026 mArrayPrototype = engine->newObject(); 0027 mArrayPrototype.setProperty(QStringLiteral("toString"), engine->newFunction(Array_proto_toString)); 0028 } 0029 0030 ArrayScriptClass::~ArrayScriptClass() = default; 0031 0032 bool ArrayScriptClass::queryAdditionalProperty(const DataInformation* data, const QScriptString& name, QScriptClass::QueryFlags* flags, uint* id) 0033 { 0034 Q_UNUSED(data) 0035 // no need to modify flags since both read and write are handled 0036 if (name == s_length) { 0037 return true; 0038 } 0039 if (name == s_type || name == s_childType) { 0040 return true; 0041 } 0042 0043 bool isArrayIndex; 0044 quint32 pos = name.toArrayIndex(&isArrayIndex); 0045 if (isArrayIndex && pos <= data->childCount()) { 0046 *id = pos + 1; // add 1 to distinguish from the default value of 0 0047 *flags &= ~HandlesWriteAccess; // writing is not yet supported 0048 return true; 0049 } 0050 return false; // not found 0051 } 0052 0053 bool ArrayScriptClass::additionalPropertyFlags(const DataInformation* data, const QScriptString& name, uint id, QScriptValue::PropertyFlags* flags) 0054 { 0055 Q_UNUSED(data) 0056 Q_UNUSED(name) 0057 if (name == s_childType) { 0058 return true; // undeleteable is on by default 0059 } 0060 if (id != 0) { 0061 *flags |= QScriptValue::ReadOnly; 0062 return true; 0063 } 0064 return false; 0065 } 0066 0067 QScriptValue ArrayScriptClass::additionalProperty(const DataInformation* data, const QScriptString& name, uint id) 0068 { 0069 const ArrayDataInformation* aData = data->asArray(); 0070 if (id != 0) { 0071 quint32 pos = id - 1; 0072 if (pos >= data->childCount()) { 0073 aData->logError() << "attempting to access out of bounds child: index was" << pos 0074 << ", length is" << data->childCount(); 0075 return engine()->currentContext()->throwError(QScriptContext::RangeError, 0076 QStringLiteral("Attempting to access array index %1, but length is %2").arg( 0077 QString::number(pos), QString::number(data->childCount()))); 0078 } 0079 0080 return aData->childToScriptValue(pos, engine(), mHandlerInfo); 0081 } 0082 if (name == s_length) { 0083 return aData->length(); 0084 } 0085 if (name == s_type) { 0086 return aData->childType(); 0087 } 0088 if (name == s_childType) { 0089 aData->logWarn() << "Using property 'childType' is deprecated, use the new name 'type' instead"; 0090 return aData->childType(); 0091 } 0092 return {}; 0093 } 0094 0095 bool ArrayScriptClass::setAdditionalProperty(DataInformation* data, const QScriptString& name, uint, const QScriptValue& value) 0096 { 0097 ArrayDataInformation* aData = data->asArray(); 0098 if (name == s_length) { 0099 if (value.isFunction()) { 0100 aData->setLengthFunction(value); 0101 } else { 0102 ParsedNumber<uint> newLength = ParserUtils::uintFromScriptValue(value); 0103 if (!newLength.isValid) { 0104 aData->logError() << "new length of array is invalid:" << newLength.string; 0105 aData->setArrayLength(0); 0106 } else { 0107 aData->setArrayLength(newLength.value); 0108 } 0109 } 0110 return true; 0111 } 0112 if (name == s_type || name == s_childType) { 0113 if (name == s_childType) { 0114 aData->logWarn() << "Using property 'childType' is deprecated, use the new name 'type' instead"; 0115 } 0116 0117 DataInformation* newChildType = ScriptValueConverter::convert(value, 0118 aData->name(), aData->logger(), aData); 0119 0120 if (!newChildType) { 0121 aData->logError() << "Failed to parse new child type:" << value.toString(); 0122 } else { 0123 aData->setArrayType(newChildType); 0124 } 0125 return true; 0126 } 0127 return false; 0128 } 0129 0130 QScriptValue ArrayScriptClass::prototype() const 0131 { 0132 return mArrayPrototype; 0133 } 0134 0135 QScriptValue ArrayScriptClass::Array_proto_toString(QScriptContext* ctx, QScriptEngine* eng) 0136 { 0137 DataInformation* data = toDataInformation(ctx->thisObject()); 0138 if (!data) { 0139 qCWarning(LOG_KASTEN_OKTETA_CONTROLLERS_STRUCTURES) << "could not cast data"; 0140 return eng->undefinedValue(); 0141 } 0142 return data->typeName(); 0143 }