void PointerDataInformation::delayedReadData(Okteta::AbstractByteArrayModel *input, Okteta::Address address) { Q_UNUSED(address); //TODO offsets Q_ASSERT(mHasBeenUpdated); //update must have been called prior to reading Q_ASSERT(mWasAbleToRead); quint8 childBitOffset = 0; // Compute the destination offset const quint64 pointer = mValue->value().value<quint64>(); if (pointer > quint64(std::numeric_limits<Okteta::Address>::max())) { logError() << "Pointer" << mValue->valueString() << "does not point to an existing address."; return; } Okteta::Address newAddress(pointer); // If the computed destination it's outside the boundaries of the input ignore it if (newAddress < 0 || newAddress >= input->size()) { logError() << "Pointer" << mValue->valueString() << "does not point to an existing address."; return; } //update the child now DataInformation* oldTarget = mPointerTarget.data(); topLevelDataInformation()->scriptHandler()->updateDataInformation(mPointerTarget.data()); // Let the child do the work (maybe different than before now) if (mPointerTarget.data() != oldTarget) { logInfo() << "Pointer target was replaced."; topLevelDataInformation()->setChildDataChanged(); } mPointerTarget->readData(input, newAddress, BitCount64(input->size() - newAddress) * 8, &childBitOffset); }
qint64 EnumDataInformation::readData(Okteta::AbstractByteArrayModel* input, Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset) { //update enum first (it is possible to change the enum definition this enum uses topLevelDataInformation()->updateElement(this); qint64 retVal = mValue->readData(input, address, bitsRemaining, bitOffset); mWasAbleToRead = retVal >= 0; //not able to read if mValue->readData returns -1 return retVal; }
qint64 PointerDataInformation::readData(Okteta::AbstractByteArrayModel* input, Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset) { qint64 ret = PrimitiveDataInformationWrapper::readData(input, address, bitsRemaining, bitOffset); if (!mWasAbleToRead) { mPointerTarget->mWasAbleToRead = false; } // If the pointer it's outside the boundaries of the input simply ignore it else if (mValue->value().value<quint64>() < quint64(input->size())) { // Enqueue for later reading of the destination topLevelDataInformation()->enqueueReadData(this); } return ret; }
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; }
qint64 AbstractBitfieldDataInformation::readData(Okteta::AbstractByteArrayModel *input, Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset) { Q_ASSERT(mHasBeenUpdated); //update must have been called prior to reading if (bitsRemaining < BitCount64(width())) { mWasAbleToRead = false; mValue = 0; return -1; } bool wasValid = mWasAbleToRead; AllPrimitiveTypes oldVal(mValue); AllPrimitiveTypes newVal(mValue); mWasAbleToRead = newVal.readBits(size(), input, effectiveByteOrder(), address, bitsRemaining, bitOffset); if (oldVal != newVal || wasValid != mWasAbleToRead) { topLevelDataInformation()->setChildDataChanged(); mValue = newVal; } return width(); }