1 /*
2     This file is part of the Okteta Kasten Framework, made within the KDE community.
3 
4     SPDX-FileCopyrightText: 2010 Alex Richardson <alex.richardson@gmx.de>
5 
6     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8 
9 #include "abstractbitfielddatainformation.hpp"
10 
11 #include <KLocalizedString>
12 
13 #include "../../topleveldatainformation.hpp"
14 
15 #include "../../../script/classes/bitfieldscriptclass.hpp"
16 #include "../../../script/scripthandlerinfo.hpp"
17 
AbstractBitfieldDataInformation(const QString & name,BitCount32 width,DataInformation * parent)18 AbstractBitfieldDataInformation::AbstractBitfieldDataInformation(const QString& name, BitCount32 width,
19                                                                  DataInformation* parent)
20     : PrimitiveDataInformation(name, parent)
21     , mWidth(qMin(width, 64u))
22 {
23     Q_ASSERT(width <= 64);
24 }
25 
26 AbstractBitfieldDataInformation::AbstractBitfieldDataInformation(const AbstractBitfieldDataInformation& d) = default;
27 
28 AbstractBitfieldDataInformation::~AbstractBitfieldDataInformation() = default;
29 
sizeString() const30 QString AbstractBitfieldDataInformation::sizeString() const
31 {
32     return i18np("%1 bit", "%1 bits", width());
33 }
34 
value() const35 AllPrimitiveTypes AbstractBitfieldDataInformation::value() const
36 {
37     return mValue;
38 }
39 
setValue(AllPrimitiveTypes newVal)40 void AbstractBitfieldDataInformation::setValue(AllPrimitiveTypes newVal)
41 {
42     Q_ASSERT((newVal.value<quint64>() & mask()) == newVal.value<quint64>());
43     mValue = newVal.value<quint64>() & mask();
44 }
45 
type() const46 PrimitiveDataType AbstractBitfieldDataInformation::type() const
47 {
48     return PrimitiveDataType::Bitfield;
49 }
50 
readData(Okteta::AbstractByteArrayModel * input,Okteta::Address address,BitCount64 bitsRemaining,quint8 * bitOffset)51 qint64 AbstractBitfieldDataInformation::readData(Okteta::AbstractByteArrayModel* input,
52                                                  Okteta::Address address, BitCount64 bitsRemaining, quint8* bitOffset)
53 {
54     Q_ASSERT(mHasBeenUpdated); // update must have been called prior to reading
55     if (bitsRemaining < BitCount64(width())) {
56         mWasAbleToRead = false;
57         mValue = 0;
58         return -1;
59     }
60     bool wasValid = mWasAbleToRead;
61     AllPrimitiveTypes oldVal(mValue);
62     AllPrimitiveTypes newVal(mValue);
63 
64     mWasAbleToRead = newVal.readBits(size(), input, effectiveByteOrder(), address, bitsRemaining,
65                                      bitOffset);
66 
67     if (oldVal != newVal || wasValid != mWasAbleToRead) {
68         topLevelDataInformation()->setChildDataChanged();
69         mValue = newVal;
70     }
71     return width();
72 }
73 
setData(const QVariant & valueVariant,Okteta::AbstractByteArrayModel * out,Okteta::Address address,BitCount64 bitsRemaining,quint8 bitOffset)74 bool AbstractBitfieldDataInformation::setData(const QVariant& valueVariant,
75                                               Okteta::AbstractByteArrayModel* out, Okteta::Address address, BitCount64 bitsRemaining,
76                                               quint8 bitOffset)
77 {
78     AllPrimitiveTypes oldVal(mValue);
79     bool ok;
80     AllPrimitiveTypes valToWrite = valueVariant.toULongLong(&ok);
81     Q_ASSERT(ok);
82     if (!ok) {
83         return false;
84     }
85     AllPrimitiveTypes newVal(oldVal);
86     // this handles remaining < size() for us
87     bool wasAbleToWrite = newVal.writeBits(width(), valToWrite, out, effectiveByteOrder(), address,
88                                            bitsRemaining, &bitOffset);
89     return wasAbleToWrite;
90 }
91 
fromVariant(const QVariant & variant,bool * ok) const92 AllPrimitiveTypes AbstractBitfieldDataInformation::fromVariant(const QVariant& variant, bool* ok) const
93 {
94     return AllPrimitiveTypes(variant.toULongLong(ok));
95 }
96 
scriptClass(ScriptHandlerInfo * handlerInfo) const97 QScriptClass* AbstractBitfieldDataInformation::scriptClass(ScriptHandlerInfo* handlerInfo) const
98 {
99     return handlerInfo->mBitfieldClass.data();
100 }
101 
size() const102 BitCount32 AbstractBitfieldDataInformation::size() const
103 {
104     return mWidth;
105 }
106 
isBitfield() const107 bool AbstractBitfieldDataInformation::isBitfield() const
108 {
109     return true;
110 }
111 
flags(int column,bool fileLoaded) const112 Qt::ItemFlags AbstractBitfieldDataInformation::flags(int column, bool fileLoaded) const
113 {
114     if (column == (int) DataInformation::ColumnValue && fileLoaded) {
115         return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
116     }
117 
118     return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
119 }
120