ksuprynowiczV8 related cleanup61924163 years agoHistory
185 lines · 5.5 KB · C
RawDownload
////  ScriptEngineCast.h//  libraries/script-engine/src////  Created by Heather Anderson on 5/9/2021.//  Copyright 2021 Vircadia contributors.//  Copyright 2022-2023 Overte e.V.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html//  SPDX-License-Identifier: Apache-2.0// /// @addtogroup ScriptEngine/// @{ #ifndef hifi_ScriptEngineCast_h#define hifi_ScriptEngineCast_h // Object conversion helpers (copied from QScriptEngine) #include <QtCore/QMetaType>#include <QtCore/QMetaEnum>#include <QtCore/QDebug> #include "ScriptEngine.h"#include "ScriptValue.h" template <typename T>inline ScriptValue scriptValueFromValue(ScriptEngine* engine, const T& t) {    if (!engine) {        return ScriptValue();    }     return engine->create(qMetaTypeId<T>(), &t);} template <>inline ScriptValue scriptValueFromValue<QVariant>(ScriptEngine* engine, const QVariant& v) {    if (!engine) {        return ScriptValue();    }     return engine->create(v.userType(), v.data());} // V8TODO: run through debugger for AnimationPointer/AnimationObjecttemplate <typename T>inline T scriptvalue_cast(const ScriptValue& value) {    const int id = qMetaTypeId<T>();     auto engine = value.engine();    if (engine) {        QVariant varValue = engine->convert(value, id);        if (varValue.isValid()) {            return varValue.value<T>();        }    }    if (value.isVariant()) {        return qvariant_cast<T>(value.toVariant());    }     return T();} template <>inline QVariant scriptvalue_cast<QVariant>(const ScriptValue& value) {    return value.toVariant();} template <typename T, ScriptValue (*f)(ScriptEngine*, const T&)>ScriptValue toScriptValueWrapper(ScriptEngine* engine, const void *p) {    Q_ASSERT(p != NULL);    auto &src = *(reinterpret_cast<const T*>(p));    return f(engine, src);} template <typename T, bool (*f)(const ScriptValue&, T&)>bool fromScriptValueWrapper(const ScriptValue& val, QVariant &destV) {    //auto &dest = *(reinterpret_cast<T*>(p));    T dest;    bool result = f(val, dest);    destV.setValue(dest);    return result;} template <typename T, ScriptValue (*toScriptValue)(ScriptEngine*, const T&), bool (*fromScriptValue)(const ScriptValue&, T&)>int scriptRegisterMetaType(ScriptEngine* eng, const char* name = "",                           T* = 0){    int id;    if (strlen(name) > 0) { // make sure it's registered        id = qRegisterMetaType<T>(name);    } else {        id = qRegisterMetaType<T>();    }    eng->registerCustomType(id, toScriptValueWrapper<T, toScriptValue>,                            fromScriptValueWrapper<T, fromScriptValue>);    return id;} // This can be safely removed and replaced with scriptRegisterMetaType once we use C++20 everywheretemplate <typename T>int scriptRegisterMetaTypeWithLambdas(ScriptEngine* eng,                           ScriptValue (*toScriptValue)(ScriptEngine*, const void *),                           bool (*fromScriptValue)(const ScriptValue&, QVariant &dest), const char* name = "",                           T* = 0){    int id;    if (strlen(name) > 0) { // make sure it's registered        id = qRegisterMetaType<T>(name);    } else {        id = qRegisterMetaType<T>();    }    eng->registerCustomType(id, toScriptValue,                            fromScriptValue);    return id;} template <class Container>ScriptValue scriptValueFromSequence(ScriptEngine* eng, const Container& cont) {    ScriptValue a = eng->newArray();    typename Container::const_iterator begin = cont.begin();    typename Container::const_iterator end = cont.end();    typename Container::const_iterator it;    quint32 i;    for (it = begin, i = 0; it != end; ++it, ++i) {        a.setProperty(i, eng->toScriptValue(*it));    }    return a;} template <class Container>bool scriptValueToSequence(const ScriptValue& value, Container& cont) {    quint32 len = value.property(QLatin1String("length")).toUInt32();    for (quint32 i = 0; i < len; ++i) {        ScriptValue item = value.property(i);        cont.push_back(scriptvalue_cast<typename Container::value_type>(item));    }    return true;} template <class T>ScriptValue scriptValueFromEnumClass(ScriptEngine* eng, const T& enumValue) {    ScriptValue a = eng->newValue(static_cast<int>(enumValue));    return a;} template <class T>bool scriptValueToEnumClass(const ScriptValue& value, T& enumValue) {    if(!value.isNumber()){        qCDebug(scriptengine) << "ScriptValue \"" << value.toQObject()->metaObject()->className() << "\" is not a number";        return false;    }    QMetaEnum metaEnum = QMetaEnum::fromType<T>();    if (!metaEnum.isValid()) {        qCDebug(scriptengine) << "Invalid QMetaEnum";        return false;    }    bool isValid = false;    int enumInteger = static_cast<int>(value.toInteger());    for(int i = 0; i < metaEnum.keyCount(); i++){        if (metaEnum.value(i) == enumInteger) {            isValid = true;            break;        }    }    if (isValid) {        enumValue = static_cast<T>(enumInteger);        return true;    } else {        qCDebug(scriptengine) << "ScriptValue has invalid value " << value.toInteger() << " for enum" << metaEnum.name();        return false;    }} template <typename T>int scriptRegisterSequenceMetaType(ScriptEngine* engine,                                   T* = 0) {    return scriptRegisterMetaType<T, scriptValueFromSequence, scriptValueToSequence>(engine);} #endif // hifi_ScriptEngineCast_h /// @}