File indexing completed on 2024-05-26 05:56:31
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2023 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 "bytearraysearchutils.hpp" 0010 0011 // Okteta core 0012 #include <Okteta/AbstractByteArrayModel> 0013 0014 namespace Kasten { 0015 0016 namespace ByteArraySearchUtils { 0017 0018 // TODO: add a compare API to AbstractByteArrayModel 0019 static 0020 bool isSearchDataEqual(const Okteta::AbstractByteArrayModel* byteArrayModel, Okteta::AddressRange selection, 0021 const QByteArray& searchData) 0022 { 0023 if (searchData.size() != selection.width()) { 0024 return false; 0025 } 0026 Okteta::Address address = selection.start(); 0027 for (int i = 0; i < searchData.size(); ++i, ++address) { 0028 if (byteArrayModel->byte(address) != static_cast<Okteta::Byte>(searchData.at(i))) { 0029 return false; 0030 } 0031 } 0032 return true; 0033 } 0034 0035 bool getSearchIndexes(Okteta::Address* searchFirstIndex, Okteta::Address* searchLastIndex, 0036 const Okteta::AbstractByteArrayModel* byteArrayModel, 0037 Okteta::AddressRange selection, 0038 Okteta::Address cursorPosition, 0039 const QByteArray& searchData, 0040 FindDirection direction, 0041 bool fromCursor, bool inSelection) 0042 { 0043 if (inSelection) { 0044 if (!selection.isValid()) { 0045 // nothing selected, so skip any search 0046 return false; 0047 } 0048 if (searchData.size() > selection.width()) { 0049 // searched data does not even fit, so skip any search 0050 // TODO: catch in dialog already 0051 return false ; 0052 } 0053 0054 *searchFirstIndex = selection.start(); 0055 *searchLastIndex = selection.end(); 0056 } else { 0057 if (searchData.size() > byteArrayModel->size()) { 0058 // searched data does not even fit, so skip any search 0059 // also handles case of empty bytearray 0060 // TODO: catch in dialog already 0061 return false; 0062 } 0063 0064 if (fromCursor) { 0065 // assuming that selection is coupled with cursor 0066 if (selection.isValid()) { 0067 // skip current selection if matching 0068 if (isSearchDataEqual(byteArrayModel, selection, searchData)) { 0069 if (direction == FindForward) { 0070 *searchFirstIndex = selection.nextBehindEnd(); 0071 *searchLastIndex = selection.end(); 0072 } else { 0073 *searchLastIndex = selection.start() - 1; 0074 *searchFirstIndex = selection.start(); 0075 } 0076 } else { 0077 // treating selection as extended cursor 0078 if (direction == FindForward) { 0079 *searchFirstIndex = selection.start(); 0080 // no wrap needed when starting at 0 0081 *searchLastIndex = (selection.start() == 0) ? byteArrayModel->size() - 1 : selection.start() - 1; 0082 } else { 0083 *searchLastIndex = selection.end(); 0084 // no wrap needed when starting at end 0085 *searchFirstIndex = (selection.end() == byteArrayModel->size() - 1) ? 0 : selection.nextBehindEnd(); 0086 } 0087 } 0088 } else { 0089 if (direction == FindForward) { 0090 *searchFirstIndex = cursorPosition; 0091 // no wrap needed when starting at 0 0092 *searchLastIndex = (*searchFirstIndex == 0) ? byteArrayModel->size() - 1 : *searchFirstIndex - 1; 0093 } else { 0094 *searchLastIndex = cursorPosition - 1; 0095 // no wrap needed when starting at end 0096 *searchFirstIndex = (*searchLastIndex == byteArrayModel->size() - 1) ? 0 : *searchLastIndex + 1; 0097 } 0098 } 0099 } else { 0100 *searchFirstIndex = 0; 0101 *searchLastIndex = byteArrayModel->size() - 1; 0102 } 0103 } 0104 0105 return true; 0106 } 0107 0108 } 0109 0110 }