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 }