File indexing completed on 2024-06-23 05:49:00

0001 /*
0002     This file is part of the Okteta Kasten Framework, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009, 2010, 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 "structuredatainformation.hpp"
0010 
0011 #include "topleveldatainformation.hpp"
0012 
0013 #include <KLocalizedString>
0014 #include <limits>
0015 
0016 StructureDataInformation::StructureDataInformation(const QString& name,
0017                                                    const QVector<DataInformation*>& children, DataInformation* parent)
0018     : DataInformationWithChildren(name, children, parent)
0019 {
0020 }
0021 
0022 StructureDataInformation::~StructureDataInformation() = default;
0023 
0024 QString StructureDataInformation::typeNameImpl() const
0025 {
0026     return i18nc("data type in C/C++, then name", "struct %1", name());
0027 }
0028 
0029 bool StructureDataInformation::isStruct() const
0030 {
0031     return true;
0032 }
0033 
0034 qint64 StructureDataInformation::readData(const Okteta::AbstractByteArrayModel* input,
0035                                           Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset)
0036 {
0037     Q_ASSERT(mHasBeenUpdated); // update must have been called prior to reading
0038     qint64 bitsRead = 0;
0039     mWasAbleToRead = readChildren(mChildren, input, address, bitsRemaining, bitOffset, &bitsRead, topLevelDataInformation());
0040     return bitsRead;
0041 }
0042 
0043 BitCount64 StructureDataInformation::childPosition(const DataInformation* child, Okteta::Address start) const
0044 {
0045     BitCount64 offset = 0;
0046     // sum size of elements up to index
0047     for (auto* current : mChildren) {
0048         if (current == child) {
0049             break;
0050         }
0051         offset += current->size();
0052     }
0053 
0054     if (mParent->isTopLevel()) {
0055         return start * 8 + offset;
0056     }
0057 
0058     return mParent->asDataInformation()->childPosition(this, start) + offset;
0059 }
0060 
0061 bool StructureDataInformation::readChildren(const QVector<DataInformation*>& children,
0062                                             const Okteta::AbstractByteArrayModel* input, Okteta::Address address, BitCount64 bitsRemaining,
0063                                             quint8* bitOffset, qint64* readBitsPtr, TopLevelDataInformation* top)
0064 {
0065     Q_CHECK_PTR(top);
0066     Q_CHECK_PTR(readBitsPtr);
0067     Q_ASSERT(*readBitsPtr >= 0); // otherwise we failed before
0068     qint64 readBits = *readBitsPtr;
0069     // prevent overflow
0070     Q_ASSERT(sizeof(qint64) == sizeof(Okteta::Address) || readBits < (qint64(std::numeric_limits<qint32>::max()) * 8));
0071     const quint8 origBitOffset = *bitOffset;
0072     Okteta::Address readBytes = (readBits + origBitOffset) / 8;
0073     for (int i = 0; i < children.size(); i++) {
0074         DataInformation* next = children.at(i);
0075         top->scriptHandler()->updateDataInformation(next);
0076         // next may be a dangling pointer now, reset it
0077         DataInformation* newNext = children.at(i);
0078         if (next != newNext) {
0079             // logInfo() << "Child at index " << i << " was replaced.";
0080             top->setChildDataChanged();
0081         }
0082         qint64 currentReadBits = newNext->readData(input, address + readBytes,
0083                                                    bitsRemaining - readBits, bitOffset);
0084         if (currentReadBits == -1) {
0085             *readBitsPtr = -1;
0086             return false; // could not read one element -> whole structure could not be read
0087         }
0088         readBits += currentReadBits;
0089         readBytes = (readBits + origBitOffset) / 8;
0090     }
0091 
0092     *readBitsPtr = readBits;
0093     return true;
0094 }