File indexing completed on 2024-04-14 15:52:43
0001 /* 0002 This file is part of the Okteta Core library, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2003, 2008-2009 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 #ifndef OKTETA_ABSTRACTBYTEARRAYMODEL_HPP 0010 #define OKTETA_ABSTRACTBYTEARRAYMODEL_HPP 0011 0012 // lib 0013 #include "oktetacore_export.hpp" 0014 #include "addressrange.hpp" 0015 #include "size.hpp" 0016 #include "byte.hpp" 0017 // Qt 0018 #include <QObject> 0019 #include <QByteArray> 0020 0021 namespace Okteta { 0022 0023 class ArrayChangeMetricsList; 0024 class CharCodec; 0025 class AbstractByteArrayModelPrivate; 0026 0027 /** could it be useful to hide the data access behind an iterator? * 0028 class KDataBufferIterator 0029 { 0030 public: 0031 bool hasNext(); 0032 char next(); 0033 protected: 0034 0035 protected: 0036 char * 0037 int Length; 0038 } 0039 0040 bool KDataBufferIterator::hasNext() 0041 { 0042 } 0043 // this function should be simple as possible 0044 char KDataBufferIterator::next() 0045 { 0046 // if next span is empty 0047 if( ) 0048 return *NextChar++; 0049 } 0050 */ 0051 0052 /** base class for all Data buffers that are used to display 0053 * TODO: think about a way to inform KHexEdit that there has been 0054 * a change in the buffer outside. what kind of changes are possible? 0055 * 0056 * Operations on the data: 0057 * 0058 * Finding: is implemented stateless. FindNext has to be done by perhaps a FindManager 0059 * Replacing: not available. Implement within a ReplaceManager 0060 * 0061 * @author Friedrich W. H. Kossebau 0062 */ 0063 0064 class OKTETACORE_EXPORT AbstractByteArrayModel : public QObject 0065 { 0066 friend class KAbstractByteArrayModelIterator; 0067 0068 Q_OBJECT 0069 0070 protected: 0071 OKTETACORE_NO_EXPORT explicit AbstractByteArrayModel(AbstractByteArrayModelPrivate* d, QObject* parent = nullptr); 0072 explicit AbstractByteArrayModel(QObject* parent = nullptr); 0073 0074 public: 0075 ~AbstractByteArrayModel() override; 0076 0077 public: // data access API 0078 /** locates working range 0079 * The idea behind is to tell buffer which range will be requested in the following time, 0080 * so that e.g. the corresponding pages will be loaded in advance 0081 * TODO: do we really need this? Where will this lead to real enhancements? 0082 * @param Range 0083 * @return @c true if successfully, @c false otherwise 0084 */ 0085 // virtual bool prepareRange( const Section &Range ) const = 0; 0086 /** convenience function, same as above */ 0087 // bool prepareRange( int Offset, int Length ) const; 0088 0089 /** creates an iterator to */ 0090 // virtual KDataBufferIterator *iterator() const = 0; 0091 /** expects pointer to memory, should be in prepared range 0092 * it is only expected to be a valid pointer until any further call 0093 * to this or any modifying function 0094 * @param Section 0095 * @return pointer to 0096 */ 0097 // virtual const char *dataSet( const Section &Section ) const = 0; 0098 /** convenience function, same as above */ 0099 // const char *dataSet( int Offset, int Length ) const; 0100 0101 /** requests a single byte 0102 * if the offset is not valid the behaviour is undefined 0103 * @param offset offset of the datum requested 0104 */ 0105 virtual Byte byte(Address offset) const = 0; 0106 0107 /** 0108 * @return the size of the data 0109 */ 0110 virtual Size size() const = 0; 0111 0112 public: // state read API 0113 /** 0114 * Default returns @c true. 0115 * @return @c true if the buffer can only be read, @c false if writing is allowed 0116 */ 0117 virtual bool isReadOnly() const; 0118 /** 0119 * @return @c true if the buffer has been modified, @c false otherwise 0120 */ 0121 virtual bool isModified() const = 0; 0122 0123 // TODO: for data outside the model using char* and int as well as QByteArray should always work, no? 0124 0125 public: // modification API 0126 /** inserts bytes copied from the given source at Position. 0127 * The original data beginnung at the position is moved 0128 * with the buffer enlarged as needed 0129 * If the buffer is readOnly this is a noop and returns 0. 0130 * @param offset 0131 * @param insertData data source 0132 * @param insertLength number of bytes to copy 0133 * @return length of inserted data 0134 */ 0135 virtual Size insert(Address offset, const Byte* insertData, int insertLength); 0136 Size insert(Address offset, const QByteArray& insertData); 0137 0138 /** removes beginning with position as much as possible 0139 * @param removeRange 0140 * @return length of removed data 0141 */ 0142 virtual Size remove(const AddressRange& removeRange); 0143 /** convenience function, behaves as above */ 0144 Size remove(Address offset, Size removeLength); 0145 0146 /** replaces as much as possible 0147 * @param removeRange 0148 * @param insertData 0149 * @param insertLength 0150 * @return length of inserted data 0151 */ 0152 virtual Size replace(const AddressRange& removeRange, const Byte* insertData, int insertLength) = 0; 0153 /** convenience function, behaves as above */ 0154 Size replace(const AddressRange& removeRange, const QByteArray& insertData); 0155 /** convenience function, behaves as above */ 0156 Size replace(Address offset, Size removeLength, 0157 const Byte* insertData, Size insertLength); 0158 0159 // todo use parameters grouped differrently? 0160 /** moves the second section before the start of the first 0161 * which is the same as moving the first behind the second. 0162 * @param firstStart position of the data where the section should be moved behind 0163 * @param secondRange data range to be moved 0164 * @return @p true if operation was successful, @p false otherwise 0165 */ 0166 virtual bool swap(Address firstStart, const AddressRange& secondRange) = 0; 0167 0168 /** 0169 * fills the buffer with the FillChar. If the buffer is to small it will be extended as much as possible. 0170 * @param fillByte byte to use 0171 * @param offset position where the filling starts 0172 * @param fillLength number of bytes to fill. If Length is -1, the buffer is filled till the end. 0173 * @return number of filled bytes 0174 */ 0175 virtual Size fill(Byte fillByte, Address offset = 0, Size fillLength = -1) = 0; 0176 Size fill(Byte fillChar, const AddressRange& fillRange); 0177 0178 /** sets a single byte 0179 * if the offset is not valid the behaviour is undefined 0180 * @param offset offset of the datum requested 0181 * @param byte new byte value 0182 */ 0183 virtual void setByte(Address offset, Byte byte) = 0; 0184 0185 /** sets the modified flag for the buffer 0186 * @param modified 0187 */ 0188 virtual void setModified(bool modified) = 0; 0189 0190 /** sets the readonly flag for the byte array if this is possible. 0191 * Default implementation does not do anything. 0192 * @param isReadOnly new state 0193 */ 0194 virtual void setReadOnly(bool isReadOnly); 0195 0196 public: // service functions 0197 /** copies the data of the section into a given array Dest. If the section extends the buffers range 0198 * the section is limited to the buffer's end. If the section is invalid the behaviour is undefined. 0199 * @param dest pointer to a char array large enough to hold the copied section 0200 * @param copyRange 0201 * @return number of copied bytes 0202 */ 0203 virtual Size copyTo(Byte* dest, const AddressRange& copyRange) const; 0204 /** convenience function, behaves as above */ 0205 Size copyTo(Byte* dest, Address offset, Size copyLength) const; 0206 0207 public: // finding API 0208 /** searches beginning with byte at Pos. 0209 * @param pattern 0210 * @param patternLength length of search string 0211 * @param fromOffset the position to start the search 0212 * @param toOffset the position to end the search (-1 is to the end of the data stream) 0213 * @return index of the first or -1 0214 */ 0215 virtual Address indexOf(const Byte* pattern, int patternLength, Address fromOffset = 0, Address toOffset = -1) const; 0216 Address indexOf(const QByteArray& pattern, Address fromOffset = 0, Address toOffset = -1) const; 0217 Address indexOfCaseInsensitive(const CharCodec* charCodec, const QByteArray& pattern, Address fromOffset = 0, Address toOffset = -1) const; 0218 0219 /** searches for a given data string 0220 * The section limits the data within which the key has to be found 0221 * If the end of the section is lower than the start the search continues at the start??? 0222 * @param 0223 * @param Length length of search string 0224 * @param Section section within the keydata is to be found 0225 * @return index of the first occurrence or -1 0226 */ 0227 // virtual int indexOf( const char*KeyData, int Length, const Section &Section ) const { return -1; }//= 0; 0228 /** searches backward beginning with byte at Pos. 0229 * @param pattern 0230 * @param patternLength length of search string 0231 * @param fromOffset the position to start the search. If -1 the search starts at the end. 0232 * @return index of the first or -1 0233 */ 0234 virtual Address lastIndexOf(const Byte* pattern, int patternLength, Address fromOffset = -1, Address toOffset = 0) const; 0235 Address lastIndexOf(const QByteArray& pattern, Address fromOffset = -1, Address toOffset = 0) const; 0236 Address lastIndexOfCaseInsensitive(const CharCodec* charCodec, const QByteArray& pattern, Address fromOffset = -1, Address toOffset = 0) const; 0237 0238 /* virtual int find( const QString &expr, bool cs, bool wo, bool forward = true, int *index = 0 ); */ 0239 0240 Q_SIGNALS: 0241 // TODO: how to deal replacing with fixed size of buffer? 0242 void contentsChanged(const Okteta::ArrayChangeMetricsList& changeList); 0243 0244 void readOnlyChanged(bool isReadOnly); 0245 void modifiedChanged(bool isModified); 0246 0247 // TODO: how to handle a typedef with signals 0248 void searchedBytes(Okteta::Size bytes) const; 0249 0250 protected: 0251 const QScopedPointer<AbstractByteArrayModelPrivate> d_ptr; 0252 0253 private: 0254 Q_DECLARE_PRIVATE(AbstractByteArrayModel) 0255 }; 0256 0257 // TODO: find why static_cast fails 0258 inline Size AbstractByteArrayModel::insert(Address offset, const QByteArray& insertData) 0259 { return insert(offset, reinterpret_cast<const Byte*>(insertData.constData()), insertData.size()); } 0260 0261 inline Size AbstractByteArrayModel::remove(Address offset, Size removeLength) 0262 { return remove(AddressRange::fromWidth(offset, removeLength)); } 0263 0264 inline Size AbstractByteArrayModel::replace(const AddressRange& removeRange, const QByteArray& insertData) 0265 { return replace(removeRange, reinterpret_cast<const Byte*>(insertData.constData()), insertData.size());} 0266 0267 inline Size AbstractByteArrayModel::replace(Address offset, Size removeLength, 0268 const Byte* insertData, Size insertLength) 0269 { return replace(AddressRange::fromWidth(offset, removeLength), insertData, insertLength); } 0270 0271 inline Size AbstractByteArrayModel::fill(const Byte fillChar, const AddressRange& fillRange) 0272 { return fill(fillChar, fillRange.start(), fillRange.width()); } 0273 0274 inline Size AbstractByteArrayModel::copyTo(Byte* dest, Address offset, Size copyLength) const 0275 { return copyTo(dest, AddressRange::fromWidth(offset, copyLength)); } 0276 0277 inline Address AbstractByteArrayModel::indexOf(const QByteArray& pattern, Address fromOffset, Address toOffset) const 0278 { return indexOf(reinterpret_cast<const Byte*>(pattern.constData()), pattern.size(), fromOffset, toOffset); } 0279 0280 inline Address AbstractByteArrayModel::lastIndexOf(const QByteArray& pattern, Address fromOffset, Address toOffset) const 0281 { return lastIndexOf(reinterpret_cast<const Byte*>(pattern.constData()), pattern.size(), fromOffset, toOffset); } 0282 0283 } 0284 0285 #endif