示例#1
0
DataInformation* OsdParser::parseNode(const QDomNode& node, const DataInformation* parent)
{
    QDomElement elem = node.toElement(); // try to convert the node to an element.
    DataInformation* data = NULL;
    if (!elem.isNull())
    {
        //      kDebug() << "element tag: " << elem.tagName();
        //e is element
        const QString tag = elem.tagName();
        if (tag == QLatin1String("struct"))
            data = structFromXML(elem);
        else if (tag == QLatin1String("array"))
            data = arrayFromXML(elem, parent);
        else if (tag == QLatin1String("bitfield"))
            data = bitfieldFromXML(elem);
        else if (tag == QLatin1String("primitive"))
            data = primitiveFromXML(elem);
        else if (tag == QLatin1String("union"))
            data = unionFromXML(elem);
        else if (tag == QLatin1String("enum"))
            data = enumFromXML(elem, false);
        else if (tag == QLatin1String("flags"))
            data = enumFromXML(elem, true);
        else if (tag == QLatin1String("string"))
            data = stringFromXML(elem);
    }
    if (data) {
        QString byteOrder = elem.attribute(QLatin1String("byteOrder"), QLatin1String("inherit"));
        data->setByteOrder(byteOrderFromString(byteOrder));
    }
    return data;
}
示例#2
0
QScriptValue::PropertyFlags DefaultScriptClass::propertyFlags(const QScriptValue& object, const QScriptString& name, uint id)
{
    QScriptValue::PropertyFlags result;
    const ScriptHandlerInfo::Mode mode = mHandlerInfo->mode();
    Q_ASSERT(mode != ScriptHandlerInfo::None);
    DataInformation* data = toDataInformation(object);
    if (!data)
    {
        mHandlerInfo->logger()->error() << "could not cast data from" << object.data().toString();
        engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Attempting to access an invalid object"));
        return 0;
    }
    if (name == s_valid || name == s_validationError)
    {
        if (mode != ScriptHandlerInfo::Validating)
            result |= QScriptValue::ReadOnly;
    }
    else if (mode != ScriptHandlerInfo::Updating)
    {
        result |= QScriptValue::ReadOnly;
    }

    for (int i = 0, size = mIterableProperties.size(); i < size; ++i) {
        if (mIterableProperties.at(i).first == name)
            return result | mIterableProperties.at(i).second;
    }
    if (additionalPropertyFlags(data, name, id, &result))
        return result; //is a child element
    else
    {
        data->logError() << "could not find flags for property with name" << name.toString();
        return 0;
    }
}
示例#3
0
void ComplexArrayData::appendChildren(uint from, uint to)
{
    for (uint i = from; i < to; ++i)
    {
        DataInformation* arrayElem = mChildType->clone();
        arrayElem->setName(QString::number(i));
        arrayElem->setParent(mParent);
        mChildren.append(arrayElem);
    }
}
示例#4
0
QScriptValue DefaultScriptClass::Default_proto_toString(QScriptContext* ctx, QScriptEngine* eng)
{
    DataInformation* data = toDataInformation(ctx->thisObject());
    if (!data)
    {
        qCWarning(LOG_KASTEN_OKTETA_CONTROLLERS_STRUCTURES) << "could not cast data";
        return eng->undefinedValue();
    }
    return QString(data->typeName() + QLatin1Char(' ') + data->name());
}
示例#5
0
QScriptString DefaultscriptClassIterator::name() const
{
    Q_ASSERT(mCurrent >= 0 && (uint)mCurrent < mClass->mIterableProperties.size() + mData->childCount());
    if (mCurrent < 0 || (uint)mCurrent >= mClass->mIterableProperties.size() + mData->childCount())
        return QScriptString();
    if (mCurrent < mClass->mIterableProperties.size())
        return mClass->mIterableProperties.at(mCurrent).first;
    int index = mCurrent - mClass->mIterableProperties.size();
    Q_ASSERT(index >= 0);
    DataInformation* child = mData->childAt(index);
    return mClass->engine()->toStringHandle(child->name());
}
示例#6
0
BitCount64 ComplexArrayData::offset(const DataInformation* child) const
{
    BitCount64 offset = 0;
    //sum size of elements up to index
    for (int i = 0; i < mChildren.size(); ++i)
    {
        DataInformation* current = mChildren.at(i);
        if (current == child)
            return offset;
        offset += current->size();
    }
    Q_ASSERT(false); //should never be reached
    return offset;
}
示例#7
0
QScriptClass::QueryFlags DefaultScriptClass::queryProperty(const QScriptValue& object,
            const QScriptString& name, QScriptClass::QueryFlags flags, uint* id)
{
    const ScriptHandlerInfo::Mode mode = mHandlerInfo->mode();
    Q_ASSERT(mode != ScriptHandlerInfo::None);
    DataInformation* data = toDataInformation(object);
    if (!data)
    {
        mHandlerInfo->logger()->error() << "could not cast data from" << object.data().toString();
        engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Attempting to access an invalid object"));
        return 0;
    }
    if (name == s_valid || name == s_validationError)
    {
        return mode == ScriptHandlerInfo::Validating ? flags : flags & ~HandlesWriteAccess;
    }
    if (mode != ScriptHandlerInfo::Updating)
    {
        //the only properties that are possibly writable when not updating are valid and validationError
        //but we checked them before so we remove handlesWriteAccess from the flags
        flags &= ~HandlesWriteAccess;
    }

    if (name == s_byteOrder || name == s_name || name == s_updateFunc || name == s_validationFunc
        || name == s_datatype || name == s_customTypeName || name == s_asStringFunc)
    {
        return flags;
    }
    else if (name == s_wasAbleToRead || name == s_parent)
    {
        return flags & ~HandlesWriteAccess;
    }
    else if (queryAdditionalProperty(data, name, &flags, id))
    {
        return flags;
    }
    else
    {
        data->logError() << "could not find property with name" << name.toString();
        engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Could not find property with name ") + name.toString());
        return 0;
    }
}
示例#8
0
qint64 UnionDataInformation::readData(Okteta::AbstractByteArrayModel *input,
        Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset)
{
    Q_ASSERT(mHasBeenUpdated); //update must have been called prior to reading
    TopLevelDataInformation* top = topLevelDataInformation();
    Q_CHECK_PTR(top);

    qint64 readBits = 0;
    const quint8 originalBitOffset = *bitOffset;
    quint8 bitOffsetAfterUnion = originalBitOffset;
    bool reachedEOF = false;
    for (int i = 0; i < mChildren.size(); i++)
    {
        DataInformation* next = mChildren.at(i);
        //first of all update the structure:
        top->scriptHandler()->updateDataInformation(next);
        DataInformation* newNext = mChildren.at(i);
        if (next != newNext)
        {
            logInfo() << "Child at index " << i << " was replaced.";
            top->setChildDataChanged();
        }
        //bit offset always has to be reset to original value
        qint64 currentReadBits = newNext->readData(input, address, bitsRemaining, bitOffset);
        if (currentReadBits == -1)
        {
            //since this is a union, try to read all values and not abort as soon as one is too large
            reachedEOF = true;
        }
        else if (currentReadBits > readBits)
        {
            //this is the largest element, so the bit offset after the union is the one after this element
            readBits = currentReadBits;
            bitOffsetAfterUnion = *bitOffset;
        }
        *bitOffset = originalBitOffset; // start at beginning
    }
    *bitOffset = bitOffsetAfterUnion;
    mWasAbleToRead = !reachedEOF;
    return reachedEOF ? -1 : readBits;
}
示例#9
0
void DefaultScriptClass::setProperty(QScriptValue& object, const QScriptString& name, uint id, const QScriptValue& value)
{
    const ScriptHandlerInfo::Mode mode = mHandlerInfo->mode();
    Q_ASSERT(mode != ScriptHandlerInfo::None);
    DataInformation* data = toDataInformation(object);
    if (!data)
    {
        mHandlerInfo->logger()->error() << "could not cast data from" << object.data().toString();
        engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Attempting to access an invalid object"));
        return;
    }
    if (mode == ScriptHandlerInfo::Validating)
    {
        //only way write access is allowed is when validating: valid and validationError
        if (data->hasBeenValidated())
            data->logError() << "Cannot modify this object, it has already been validated!";
        else if (name == s_valid)
            data->mValidationSuccessful = value.toBool();
        else if (name == s_validationError)
            data->setValidationError(value.toString());
        else
            data->logError() << "Cannot write to property" << name.toString() << "while validating!";
        return;
    }

    if (mode != ScriptHandlerInfo::Updating)
    {
        data->logError() << "Writing to property" << name.toString() << "is only allowed when updating.";
        return;
    }
    Q_ASSERT(mode == ScriptHandlerInfo::Updating);

    if (name == s_byteOrder)
    {
        data->setByteOrder(ParserUtils::byteOrderFromString(value.toString(),
                LoggerWithContext(data->logger(), data->fullObjectPath())));
    }
    else if (name == s_datatype)
    {
        //change the type of the underlying object
        setDataType(value, data);
    }
    else if (name == s_updateFunc)
    {
        data->setUpdateFunc(value);
    }
    else if (name == s_validationFunc)
    {
        data->setValidationFunc(value);
    }
    else if (name == s_name)
    {
        data->setName(value.toString());
    }
    else if (name == s_customTypeName)
    {
        if (!value.isValid() || value.isNull() || value.isUndefined())
            data->setCustomTypeName(QString()); //unset
        else
            data->setCustomTypeName(value.toString());
    }
    else if (name == s_asStringFunc)
    {
        data->setToStringFunction(value);
    }
    else
    {
        bool setAdditional = setAdditionalProperty(data, name, id, value);
        if (setAdditional)
            return;
        else
        {
            data->logError() << "could not set property with name" << name.toString();
            engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Cannot write property ") + name.toString());
        }
    }
}
示例#10
0
void DefaultScriptClass::setDataType(const QScriptValue& value, DataInformation* data)
{
    DataInformation* thisObj = toDataInformation(engine()->currentContext()->thisObject());
    Q_CHECK_PTR(thisObj);
    const bool isThisObj = thisObj == data;
    //this object always has mHasBeenUpdated set just before calling updateFunc, so in that case it is okay
    if (data->hasBeenUpdated() && !isThisObj)
    {
        //this element has already been updated (and probably read, replacing it could cause crazy errors
        data->logError() << "Attempting to replace an already updated object. This could cause errors."
                "Current this object: " << (thisObj ? thisObj->fullObjectPath() : QString());
        return;
    }
    //change the type of the underlying object
    DataInformation* newType = ScriptValueConverter::convert(value, data->name(), data->logger(), data);
    if (!newType)
    {
        data->logError() << "Failed to set new type, could not convert value!";
        return;
    }

    DataInformationBase* parent = data->parent();
    Q_CHECK_PTR(parent);
    TopLevelDataInformation* top = data->topLevelDataInformation();
    Q_CHECK_PTR(top);
    //only if parent is toplevel, struct or union, can we replace
    bool replaced = false;
    if (parent->isTopLevel())
    {
        Q_ASSERT(isThisObj); //we can only do this if we are currently at the top level element
        parent->asTopLevel()->setActualDataInformation(newType);
        replaced = true;
    }
    else if (parent->isStruct())
    {
        StructureDataInformation* stru = parent->asStruct();
        int index = stru->indexOf(data);
        Q_ASSERT(index != -1);
        Q_ASSERT(uint(index) < stru->childCount());
        replaced = stru->replaceChildAt(index, newType);
        if (!replaced)
            stru->logError() << "failed to replace child at index" << index;
    }
    else if (parent->isUnion())
    {
        UnionDataInformation* un = parent->asUnion();
        int index = un->indexOf(data);
        Q_ASSERT(index != -1);
        Q_ASSERT(uint(index) < un->childCount());
        replaced = un->replaceChildAt(index, newType);
        if (!replaced)
            un->logError() << "failed to replace child at index" << index;
    }
    else if (parent->isPointer())
    {
        parent->asPointer()->setPointerTarget(newType);
        replaced = true;
    }
    else
    {
        data->logError() << "Failed to set data type since element is not toplevel and parent"
                " is neither struct nor union nor pointer.";
    }
    if (replaced)
    {
        top->setChildDataChanged();
        //if the current object was "this" in javascript we have to replace it
        if (isThisObj)
            engine()->currentContext()->setThisObject(newType->toScriptValue(engine(), mHandlerInfo));
        newType->mHasBeenUpdated = true;
    }
    else
    {
        delete newType; //could not set new type
    }
}
示例#11
0
QScriptValue DefaultScriptClass::property(const QScriptValue& object, const QScriptString& name, uint id)
{
    Q_ASSERT(mHandlerInfo->mode() != ScriptHandlerInfo::None);
    DataInformation* data = toDataInformation(object);
    if (!data)
    {
        mHandlerInfo->logger()->error() << "could not cast data from" << object.data().toString();
        return engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Attempting to access an invalid object"));
    }
    if (name == s_valid)
    {
        return data->validationSuccessful();
    }
    else if (name == s_wasAbleToRead)
    {
        return data->wasAbleToRead();
    }
    else if (name == s_parent)
    {
        Q_CHECK_PTR(data->parent());
        //parent() cannot be null
        if (data->parent()->isTopLevel())
            return engine()->nullValue();
        return data->parent()->asDataInformation()->toScriptValue(engine(), mHandlerInfo);
    }
    else if (name == s_datatype)
    {
        return data->typeName();
    }
    else if (name == s_updateFunc)
    {
        return data->updateFunc();
    }
    else if (name == s_validationFunc)
    {
        return data->validationFunc();
    }
    else if (name == s_validationError)
    {
        return data->validationError();
    }
    else if (name == s_byteOrder)
    {
        return ParserUtils::byteOrderToString(data->byteOrder());
    }
    else if (name == s_name)
    {
        return data->name();
    }
    else if (name == s_customTypeName)
    {
        return data->typeName();
    }
    else if (name == s_asStringFunc)
    {
        return data->toStringFunction();
    }
    QScriptValue other = additionalProperty(data, name, id);
    if (other.isValid())
        return other;
    else
    {
        data->logError() << "could not find property with name" << name.toString();
        return engine()->currentContext()->throwError(QScriptContext::ReferenceError,
                QStringLiteral("Cannot read property ") + name.toString());
    }
}
示例#12
0
文件: osdparser.cpp 项目: KDE/okteta
QVector<TopLevelDataInformation*> OsdParser::parseStructures() const
{
    QFileInfo fileInfo(mAbsolutePath);

    QVector<TopLevelDataInformation*> structures;
    QScopedPointer<ScriptLogger> rootLogger(new ScriptLogger()); //only needed in we get an error right now
    QDomDocument document = openDoc(rootLogger.data());
    if (document.isNull())
    {
        structures.append(new TopLevelDataInformation(
                new DummyDataInformation(0, fileInfo.fileName()), rootLogger.take(), 0, fileInfo));
        return structures;
    }

    QDomElement rootElem = document.firstChildElement(QStringLiteral("data"));
    if (rootElem.isNull())
    {
        rootLogger->error() << "Missing top level <data> element!";
        structures.append(new TopLevelDataInformation(
                new DummyDataInformation(0, fileInfo.fileName()), rootLogger.take(), 0, fileInfo));
        return structures;
    }
    int count = 1;
    for (QDomElement elem = rootElem.firstChildElement(); !elem.isNull(); elem = elem.nextSiblingElement())
    {
        if (elem.tagName() == TYPE_ENUMDEF)
            continue; //skip enum defs

        QScriptEngine* eng = ScriptEngineInitializer::newEngine(); //we need this for dynamic arrays
        ScriptLogger* logger = new ScriptLogger();
        QVector<EnumDefinition::Ptr> enums = parseEnums(rootElem, logger);
        OsdParserInfo info(QString(), logger, 0, eng, enums);

        DataInformation* data = parseElement(elem, info);

        if (!data)
        {
            QString name = readProperty(elem, PROPERTY_NAME);
            if (name.isEmpty())
                name = fileInfo.absoluteFilePath() + QStringLiteral("_element") + QString::number(count);
            qCDebug(LOG_KASTEN_OKTETA_CONTROLLERS_STRUCTURES) << "Failed to parse element" << elem.tagName() << name;
            qCDebug(LOG_KASTEN_OKTETA_CONTROLLERS_STRUCTURES) << "Parsing messages were:" << logger->messages();
            data = new DummyDataInformation(0, name);
        }
        TopLevelDataInformation* topData = new TopLevelDataInformation(data, logger, eng, fileInfo);
        QString lockOffsetStr = readProperty(elem, PROPERTY_DEFAULT_LOCK_OFFSET);
        if (!lockOffsetStr.isEmpty())
        {
            ParsedNumber<quint64> offset = ParserUtils::uint64FromString(lockOffsetStr);
            if (!offset.isValid)
                data->logError() << "Default lock offset is not a valid number:" << offset.string;
            else
            {
                data->logInfo() << "Default lock offset is " << offset.string;
                topData->setDefaultLockOffset(offset.value);
            }
        }
        structures.append(topData);
        count++;
    }
    return structures;
}