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