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"