File indexing completed on 2024-06-23 05:48:48
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2009, 2022 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "modsum64bytearraychecksumalgorithm.hpp" 0010 0011 // Okteta core 0012 #include <Okteta/AbstractByteArrayModel> 0013 // KF 0014 #include <KConfigGroup> 0015 #include <KLocalizedString> 0016 // Qt 0017 #include <QtEndian> 0018 0019 static constexpr char ModSum64ConfigGroupId[] = "ModularSum64"; 0020 0021 ModSum64ByteArrayChecksumAlgorithm::ModSum64ByteArrayChecksumAlgorithm() 0022 : AbstractByteArrayChecksumAlgorithm( 0023 i18nc("name of the checksum algorithm", "Modular sum 64-bit"), 0024 QStringLiteral("ModularSum64") 0025 ) 0026 {} 0027 0028 ModSum64ByteArrayChecksumAlgorithm::~ModSum64ByteArrayChecksumAlgorithm() = default; 0029 0030 AbstractByteArrayChecksumParameterSet* ModSum64ByteArrayChecksumAlgorithm::parameterSet() { return &mParameterSet; } 0031 0032 void ModSum64ByteArrayChecksumAlgorithm::loadConfig(const KConfigGroup& configGroup) 0033 { 0034 const KConfigGroup algorithmConfigGroup = configGroup.group(ModSum64ConfigGroupId); 0035 0036 mParameterSet.loadConfig(algorithmConfigGroup); 0037 } 0038 0039 void ModSum64ByteArrayChecksumAlgorithm::saveConfig(KConfigGroup& configGroup) const 0040 { 0041 KConfigGroup algorithmConfigGroup = configGroup.group(ModSum64ConfigGroupId); 0042 0043 mParameterSet.saveConfig(algorithmConfigGroup); 0044 } 0045 0046 bool ModSum64ByteArrayChecksumAlgorithm::calculateChecksum(QString* result, 0047 const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const 0048 { 0049 const bool useLittleEndian = (mParameterSet.endianness() == QSysInfo::LittleEndian); 0050 quint64 modSum = useLittleEndian ? 0051 calculateModSumWithLittleEndian(model, range) : 0052 calculateModSumWithBigEndian(model, range); 0053 0054 modSum = ~modSum + 1; 0055 0056 if (useLittleEndian) { 0057 modSum = qbswap(modSum); 0058 } 0059 0060 *result = QStringLiteral("%1").arg(modSum, 16, 16, QChar::fromLatin1('0')); 0061 return true; 0062 } 0063 0064 quint64 ModSum64ByteArrayChecksumAlgorithm::calculateModSumWithBigEndian(const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const 0065 { 0066 quint64 modSum = 0x00000000; 0067 Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit; 0068 0069 // TODO: move padding checks into extra code before and after loop 0070 for (Okteta::Address i = range.start(); i <= range.end(); ++i) { 0071 quint64 value = (quint64)((quint8)(model->byte(i))) << 56; 0072 ++i; 0073 if (i <= range.end()) { 0074 value |= (quint64)((quint8)(model->byte(i))) << 48; 0075 ++i; 0076 if (i <= range.end()) { 0077 value |= (quint64)((quint8)(model->byte(i))) << 40; 0078 ++i; 0079 if (i <= range.end()) { 0080 value |= (quint64)((quint8)(model->byte(i))) << 32; 0081 ++i; 0082 if (i <= range.end()) { 0083 value |= (quint64)((quint8)(model->byte(i))) << 24; 0084 ++i; 0085 if (i <= range.end()) { 0086 value |= (quint64)((quint8)(model->byte(i))) << 16; 0087 ++i; 0088 if (i <= range.end()) { 0089 value |= (quint64)((quint8)(model->byte(i))) << 8; 0090 ++i; 0091 if (i <= range.end()) { 0092 value |= (quint64)((quint8)(model->byte(i))); 0093 } 0094 } 0095 } 0096 } 0097 } 0098 } 0099 } 0100 0101 modSum += value; 0102 #if 0 0103 const uchar value = (crcBits & 0xFF) + model->byte(i); 0104 crcBits >>= 8; 0105 crcBits ^= lookupTable[value]; 0106 #endif 0107 if (i >= nextBlockEnd) { 0108 nextBlockEnd += CalculatedByteCountSignalLimit; 0109 Q_EMIT calculatedBytes(range.localIndex(i) + 1); 0110 } 0111 } 0112 0113 return modSum; 0114 } 0115 0116 quint64 ModSum64ByteArrayChecksumAlgorithm::calculateModSumWithLittleEndian(const Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const 0117 { 0118 quint64 modSum = 0x00000000; 0119 Okteta::Address nextBlockEnd = range.start() + CalculatedByteCountSignalLimit; 0120 0121 // TODO: move padding checks into extra code before and after loop 0122 for (Okteta::Address i = range.start(); i <= range.end(); ++i) { 0123 quint64 value = (quint8)(model->byte(i)); 0124 ++i; 0125 if (i <= range.end()) { 0126 value |= (quint64)((quint8)(model->byte(i))) << 8; 0127 ++i; 0128 if (i <= range.end()) { 0129 value |= (quint64)((quint8)(model->byte(i))) << 16; 0130 ++i; 0131 if (i <= range.end()) { 0132 value |= (quint64)((quint8)(model->byte(i))) << 24; 0133 ++i; 0134 if (i <= range.end()) { 0135 value |= (quint64)((quint8)(model->byte(i))) << 32; 0136 ++i; 0137 if (i <= range.end()) { 0138 value |= (quint64)((quint8)(model->byte(i))) << 40; 0139 ++i; 0140 if (i <= range.end()) { 0141 value |= (quint64)((quint8)(model->byte(i))) << 48; 0142 ++i; 0143 if (i <= range.end()) { 0144 value |= (quint64)((quint8)(model->byte(i))) << 56; 0145 } 0146 } 0147 } 0148 } 0149 } 0150 } 0151 } 0152 0153 modSum += value; 0154 #if 0 0155 const uchar value = (crcBits & 0xFF) + model->byte(i); 0156 crcBits >>= 8; 0157 crcBits ^= lookupTable[value]; 0158 #endif 0159 if (i >= nextBlockEnd) { 0160 nextBlockEnd += CalculatedByteCountSignalLimit; 0161 Q_EMIT calculatedBytes(range.localIndex(i) + 1); 0162 } 0163 } 0164 0165 return modSum; 0166 } 0167 0168 #include "moc_modsum64bytearraychecksumalgorithm.cpp"