1 /* 2 This file is part of the Okteta Kasten module, made within the KDE community. 3 4 SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <kossebau@kde.org> 5 6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 7 */ 8 9 #include "rotatebytearrayfilter.hpp" 10 11 // Okteta core 12 #include <Okteta/AbstractByteArrayModel> 13 // KF 14 #include <KLocalizedString> 15 // Qt 16 #include <QtGlobal> 17 // Std 18 #include <cstdlib> 19 20 static constexpr int RotateBitsPerByte = 8; 21 RotateByteArrayFilter()22RotateByteArrayFilter::RotateByteArrayFilter() 23 : AbstractByteArrayFilter( 24 i18nc("name of the filter; it moves the bits and pushes the ones over the end to the begin again", 25 "ROTATE data")) 26 {} 27 28 RotateByteArrayFilter::~RotateByteArrayFilter() = default; 29 parameterSet()30AbstractByteArrayFilterParameterSet* RotateByteArrayFilter::parameterSet() { return &mParameterSet; } 31 filter(Okteta::Byte * result,Okteta::AbstractByteArrayModel * model,const Okteta::AddressRange & range) const32bool RotateByteArrayFilter::filter(Okteta::Byte* result, 33 Okteta::AbstractByteArrayModel* model, const Okteta::AddressRange& range) const 34 { 35 const int groupSize = mParameterSet.groupSize(); 36 const int groupBitCount = (groupSize * RotateBitsPerByte); 37 const int groupShiftBitWidth = std::abs(mParameterSet.moveBitWidth()) % groupBitCount; 38 39 const int shiftByteWidth = groupShiftBitWidth / RotateBitsPerByte; 40 const int shiftBitWidth = groupShiftBitWidth - shiftByteWidth * RotateBitsPerByte; 41 const int otherShiftBitWidth = RotateBitsPerByte - shiftBitWidth; 42 int filteredBytesCount = 0; 43 44 const bool toRight = (mParameterSet.moveBitWidth() > 0); 45 if (toRight) { 46 int r = 0; 47 Okteta::Address m = range.start(); 48 while (m <= range.end()) { 49 int g = 0; 50 // round the edge byte layer shift 51 while (g < shiftByteWidth && m + groupSize <= range.end()) { 52 result[r++] = model->byte((m++) + groupSize - shiftByteWidth); 53 ++g; 54 } 55 // normal byte layer shift 56 while (g < groupSize && m <= range.end()) { 57 result[r++] = model->byte((m++) - shiftByteWidth); 58 ++g; 59 } 60 61 // bit layer shift 62 const unsigned char last = (unsigned char) result[r - 1]; 63 for (int b = 1; b <= g; ++b) { 64 result[r - b] = (unsigned char)result[r - b] >> shiftBitWidth; 65 if (b < g) { 66 result[r - b] |= (unsigned char)result[r - b - 1] << otherShiftBitWidth; 67 } else if (g == groupSize) { 68 result[r - b] |= last << otherShiftBitWidth; 69 } 70 } 71 72 filteredBytesCount += g; 73 if (filteredBytesCount >= FilteredByteCountSignalLimit) { 74 filteredBytesCount = 0; 75 emit filteredBytes(m - range.start()); 76 } 77 } 78 } else { 79 int r = 0; 80 Okteta::Address m = range.start(); 81 while (m <= range.end()) { 82 int g = 0; 83 // normal byte layer shift 84 while (g + shiftByteWidth < groupSize && m + shiftByteWidth <= range.end()) { 85 result[r++] = model->byte((m++) - shiftByteWidth); 86 ++g; 87 } 88 // round the edge byte layer shift 89 while (g < groupSize && m <= range.end()) { 90 result[r++] = model->byte((m++) + shiftByteWidth - groupSize); 91 ++g; 92 } 93 94 // bit layer shift 95 const unsigned char first = result[r - g]; 96 for (int b = g; b > 0; --b) { 97 result[r - b] = (unsigned char)result[r - b] << shiftBitWidth; 98 if (b > 1) { 99 result[r - b] |= (unsigned char)result[r - b + 1] >> otherShiftBitWidth; 100 } else if (g == groupSize) { 101 result[r - b] |= first >> otherShiftBitWidth; 102 } 103 } 104 105 filteredBytesCount += g; 106 if (filteredBytesCount >= FilteredByteCountSignalLimit) { 107 filteredBytesCount = 0; 108 emit filteredBytes(m - range.start()); 109 } 110 } 111 } 112 113 return true; 114 } 115