File indexing completed on 2024-04-21 16:33:50
0001 /* 0002 This file is part of the Okteta Core library, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2008 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_ARRAYCHANGEMETRICS_HPP 0010 #define OKTETA_ARRAYCHANGEMETRICS_HPP 0011 0012 // lib 0013 #include "oktetacore_export.hpp" 0014 #include "size.hpp" 0015 #include "address.hpp" 0016 // Qt 0017 #include <QDataStream> 0018 0019 namespace Okteta { 0020 0021 // TODO: do we need the invalid status? 0022 class OKTETACORE_EXPORT ArrayChangeMetrics 0023 { 0024 friend QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics); 0025 friend QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics); 0026 0027 private: 0028 static constexpr Address InvalidAddress = -1; 0029 0030 public: 0031 enum Type 0032 { 0033 // Insertion, 0034 // Removal, 0035 Replacement, 0036 Swapping, 0037 // Filling, 0038 // Setting, 0039 Invalid 0040 }; 0041 0042 public: 0043 static constexpr ArrayChangeMetrics asReplacement(Address offset, Size removeLength, Size insertLength); 0044 static constexpr ArrayChangeMetrics asSwapping(Address firstOffset, Address secondOffset, Size secondLength); 0045 0046 public: 0047 ArrayChangeMetrics() = default; 0048 ArrayChangeMetrics(const ArrayChangeMetrics&) = default; 0049 constexpr ArrayChangeMetrics(Type type, Address offset, qint32 secondArgument, qint32 thirdArgument); 0050 0051 ~ArrayChangeMetrics() = default; 0052 0053 ArrayChangeMetrics& operator=(const ArrayChangeMetrics&) = default; 0054 0055 public: 0056 constexpr bool operator==(const ArrayChangeMetrics& other) const; 0057 0058 public: 0059 void revert(); 0060 0061 public: 0062 constexpr int type() const; 0063 constexpr Address offset() const; 0064 constexpr bool isValid() const; 0065 0066 public: // Replacement properties 0067 constexpr Size removeLength() const; 0068 constexpr Size insertLength() const; 0069 constexpr Size lengthChange() const; 0070 0071 public: // Swapping properties 0072 constexpr Size firstLength() const; 0073 constexpr Address secondStart() const; 0074 constexpr Address secondEnd() const; 0075 constexpr Size secondLength() const; 0076 0077 private: 0078 Type mType = Invalid; 0079 Address mOffset = InvalidAddress; 0080 // TODO: how to make the arguments of the size of the largest union member? 0081 union 0082 { 0083 qint32 mSecondArgument = 0; 0084 Size mRemoveLength; 0085 Address mSecondStart; 0086 }; 0087 union 0088 { 0089 qint32 mThirdArgument = 0; 0090 Size mInsertLength; 0091 Size mSecondLength; 0092 }; 0093 }; 0094 0095 inline constexpr ArrayChangeMetrics ArrayChangeMetrics::asReplacement(Address offset, Size removeLength, Size insertLength) 0096 { 0097 return {Replacement, offset, removeLength, insertLength}; 0098 } 0099 0100 inline constexpr ArrayChangeMetrics ArrayChangeMetrics::asSwapping(Address firstOffset, Address secondOffset, Size secondLength) 0101 { 0102 return 0103 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) 0104 Q_ASSERT(firstOffset < secondOffset), 0105 #endif 0106 ArrayChangeMetrics{Swapping, firstOffset, secondOffset, secondLength}; 0107 } 0108 0109 inline constexpr ArrayChangeMetrics::ArrayChangeMetrics(Type type, Address offset, qint32 secondArgument, qint32 thirdArgument) 0110 : mType(type) 0111 , mOffset(offset) 0112 , mSecondArgument(secondArgument) 0113 , mThirdArgument(thirdArgument) 0114 {} 0115 inline constexpr bool ArrayChangeMetrics::operator==(const ArrayChangeMetrics& other) const 0116 { 0117 return mType == other.mType 0118 && mOffset == other.mOffset 0119 && mSecondArgument == other.mSecondArgument 0120 && mThirdArgument == other.mThirdArgument; 0121 } 0122 inline void ArrayChangeMetrics::revert() 0123 { 0124 if (mType == Replacement) { 0125 const Size helper = mInsertLength; 0126 mInsertLength = mRemoveLength; 0127 mRemoveLength = helper; 0128 } else if (mType == Swapping) { 0129 const Size oldSecondLength = mSecondLength; 0130 mSecondLength = firstLength(); 0131 mSecondStart = mOffset + oldSecondLength; 0132 } 0133 } 0134 0135 inline constexpr bool ArrayChangeMetrics::isValid() const { return mOffset != InvalidAddress; } 0136 inline constexpr int ArrayChangeMetrics::type() const { return mType; } 0137 inline constexpr Address ArrayChangeMetrics::offset() const { return mOffset; } 0138 inline constexpr Size ArrayChangeMetrics::removeLength() const { return mRemoveLength; } 0139 inline constexpr Size ArrayChangeMetrics::insertLength() const { return mInsertLength; } 0140 inline constexpr Size ArrayChangeMetrics::lengthChange() const { return mInsertLength - mRemoveLength; } 0141 inline constexpr Address ArrayChangeMetrics::secondStart() const { return mSecondStart; } 0142 inline constexpr Address ArrayChangeMetrics::secondEnd() const { return mSecondStart + mSecondLength - 1; } 0143 inline constexpr Size ArrayChangeMetrics::firstLength() const { return mSecondStart - mOffset; } 0144 inline constexpr Size ArrayChangeMetrics::secondLength() const { return mSecondLength; } 0145 0146 QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics); 0147 QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics); 0148 0149 inline QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics) 0150 { 0151 outStream << metrics.mType << metrics.mOffset << metrics.mSecondArgument << metrics.mThirdArgument; 0152 return outStream; 0153 } 0154 0155 inline QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics) 0156 { 0157 int type; 0158 inStream >> type >> metrics.mOffset >> metrics.mSecondArgument >> metrics.mThirdArgument; 0159 metrics.mType = (ArrayChangeMetrics::Type)type; // TODO: find out how to stream to enum directly 0160 return inStream; 0161 } 0162 0163 } 0164 0165 Q_DECLARE_TYPEINFO(Okteta::ArrayChangeMetrics, Q_MOVABLE_TYPE); 0166 0167 #endif