File indexing completed on 2024-06-23 05:48:49
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2008, 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 "rotatebytearrayfilter.hpp" 0010 0011 // Okteta core 0012 #include <Okteta/AbstractByteArrayModel> 0013 // KF 0014 #include <KConfigGroup> 0015 #include <KLocalizedString> 0016 // Std 0017 #include <cstdlib> 0018 0019 static constexpr char RotateFilterConfigGroupId[] = "Rotate"; 0020 0021 static constexpr int RotateBitsPerByte = 8; 0022 0023 RotateByteArrayFilter::RotateByteArrayFilter() 0024 : AbstractByteArrayFilter( 0025 i18nc("name of the filter; it moves the bits and pushes the ones over the end to the begin again", 0026 "ROTATE data"), 0027 QStringLiteral("Rotate") 0028 ) 0029 {} 0030 0031 RotateByteArrayFilter::~RotateByteArrayFilter() = default; 0032 0033 AbstractByteArrayFilterParameterSet* RotateByteArrayFilter::parameterSet() { return &mParameterSet; } 0034 0035 void RotateByteArrayFilter::loadConfig(const KConfigGroup& configGroup) 0036 { 0037 const KConfigGroup filterConfigGroup = configGroup.group(RotateFilterConfigGroupId); 0038 0039 mParameterSet.loadConfig(filterConfigGroup); 0040 } 0041 0042 void RotateByteArrayFilter::saveConfig(KConfigGroup& configGroup) const 0043 { 0044 KConfigGroup filterConfigGroup = configGroup.group(RotateFilterConfigGroupId); 0045 0046 mParameterSet.saveConfig(filterConfigGroup); 0047 } 0048 0049 bool RotateByteArrayFilter::filter(Okteta::Byte* result, 0050 Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const 0051 { 0052 const int groupSize = mParameterSet.groupSize(); 0053 const int groupBitCount = (groupSize * RotateBitsPerByte); 0054 const int groupShiftBitWidth = std::abs(mParameterSet.moveBitWidth()) % groupBitCount; 0055 0056 const int shiftByteWidth = groupShiftBitWidth / RotateBitsPerByte; 0057 const int shiftBitWidth = groupShiftBitWidth - shiftByteWidth * RotateBitsPerByte; 0058 const int otherShiftBitWidth = RotateBitsPerByte - shiftBitWidth; 0059 int filteredBytesCount = 0; 0060 0061 const bool toRight = (mParameterSet.moveBitWidth() > 0); 0062 if (toRight) { 0063 int r = 0; 0064 Okteta::Address m = range.start(); 0065 while (m <= range.end()) { 0066 int g = 0; 0067 // round the edge byte layer shift 0068 while (g < shiftByteWidth && m + groupSize <= range.end()) { 0069 result[r++] = model->byte((m++) + groupSize - shiftByteWidth); 0070 ++g; 0071 } 0072 // normal byte layer shift 0073 while (g < groupSize && m <= range.end()) { 0074 result[r++] = model->byte((m++) - shiftByteWidth); 0075 ++g; 0076 } 0077 0078 // bit layer shift 0079 const auto last = static_cast<unsigned char>(result[r - 1]); 0080 for (int b = 1; b <= g; ++b) { 0081 result[r - b] = (unsigned char)result[r - b] >> shiftBitWidth; 0082 if (b < g) { 0083 result[r - b] |= (unsigned char)result[r - b - 1] << otherShiftBitWidth; 0084 } else if (g == groupSize) { 0085 result[r - b] |= last << otherShiftBitWidth; 0086 } 0087 } 0088 0089 filteredBytesCount += g; 0090 if (filteredBytesCount >= FilteredByteCountSignalLimit) { 0091 filteredBytesCount = 0; 0092 Q_EMIT filteredBytes(m - range.start()); 0093 } 0094 } 0095 } else { 0096 int r = 0; 0097 Okteta::Address m = range.start(); 0098 while (m <= range.end()) { 0099 int g = 0; 0100 // normal byte layer shift 0101 while (g + shiftByteWidth < groupSize && m + shiftByteWidth <= range.end()) { 0102 result[r++] = model->byte((m++) - shiftByteWidth); 0103 ++g; 0104 } 0105 // round the edge byte layer shift 0106 while (g < groupSize && m <= range.end()) { 0107 result[r++] = model->byte((m++) + shiftByteWidth - groupSize); 0108 ++g; 0109 } 0110 0111 // bit layer shift 0112 const unsigned char first = result[r - g]; 0113 for (int b = g; b > 0; --b) { 0114 result[r - b] = (unsigned char)result[r - b] << shiftBitWidth; 0115 if (b > 1) { 0116 result[r - b] |= (unsigned char)result[r - b + 1] >> otherShiftBitWidth; 0117 } else if (g == groupSize) { 0118 result[r - b] |= first >> otherShiftBitWidth; 0119 } 0120 } 0121 0122 filteredBytesCount += g; 0123 if (filteredBytesCount >= FilteredByteCountSignalLimit) { 0124 filteredBytesCount = 0; 0125 Q_EMIT filteredBytes(m - range.start()); 0126 } 0127 } 0128 } 0129 0130 return true; 0131 } 0132 0133 #include "moc_rotatebytearrayfilter.cpp"