File indexing completed on 2024-04-28 09:48:28
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 Q_ASSERT(firstOffset < secondOffset), 0104 ArrayChangeMetrics{Swapping, firstOffset, secondOffset, secondLength}; 0105 } 0106 0107 inline constexpr ArrayChangeMetrics::ArrayChangeMetrics(Type type, Address offset, qint32 secondArgument, qint32 thirdArgument) 0108 : mType(type) 0109 , mOffset(offset) 0110 , mSecondArgument(secondArgument) 0111 , mThirdArgument(thirdArgument) 0112 {} 0113 inline constexpr bool ArrayChangeMetrics::operator==(const ArrayChangeMetrics& other) const 0114 { 0115 return mType == other.mType 0116 && mOffset == other.mOffset 0117 && mSecondArgument == other.mSecondArgument 0118 && mThirdArgument == other.mThirdArgument; 0119 } 0120 inline void ArrayChangeMetrics::revert() 0121 { 0122 if (mType == Replacement) { 0123 const Size helper = mInsertLength; 0124 mInsertLength = mRemoveLength; 0125 mRemoveLength = helper; 0126 } else if (mType == Swapping) { 0127 const Size oldSecondLength = mSecondLength; 0128 mSecondLength = firstLength(); 0129 mSecondStart = mOffset + oldSecondLength; 0130 } 0131 } 0132 0133 inline constexpr bool ArrayChangeMetrics::isValid() const { return mOffset != InvalidAddress; } 0134 inline constexpr int ArrayChangeMetrics::type() const { return mType; } 0135 inline constexpr Address ArrayChangeMetrics::offset() const { return mOffset; } 0136 inline constexpr Size ArrayChangeMetrics::removeLength() const { return mRemoveLength; } 0137 inline constexpr Size ArrayChangeMetrics::insertLength() const { return mInsertLength; } 0138 inline constexpr Size ArrayChangeMetrics::lengthChange() const { return mInsertLength - mRemoveLength; } 0139 inline constexpr Address ArrayChangeMetrics::secondStart() const { return mSecondStart; } 0140 inline constexpr Address ArrayChangeMetrics::secondEnd() const { return mSecondStart + mSecondLength - 1; } 0141 inline constexpr Size ArrayChangeMetrics::firstLength() const { return mSecondStart - mOffset; } 0142 inline constexpr Size ArrayChangeMetrics::secondLength() const { return mSecondLength; } 0143 0144 QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics); 0145 QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics); 0146 0147 inline QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics) 0148 { 0149 outStream << metrics.mType << metrics.mOffset << metrics.mSecondArgument << metrics.mThirdArgument; 0150 return outStream; 0151 } 0152 0153 inline QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics) 0154 { 0155 int type; 0156 inStream >> type >> metrics.mOffset >> metrics.mSecondArgument >> metrics.mThirdArgument; 0157 metrics.mType = (ArrayChangeMetrics::Type)type; // TODO: find out how to stream to enum directly 0158 return inStream; 0159 } 0160 0161 } 0162 0163 Q_DECLARE_TYPEINFO(Okteta::ArrayChangeMetrics, Q_MOVABLE_TYPE); 0164 0165 #endif