forked from KDE/okteta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharraychangemetrics.hpp
178 lines (150 loc) · 5.67 KB
/
arraychangemetrics.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
This file is part of the Okteta Core library, made within the KDE community.
SPDX-FileCopyrightText: 2008 Friedrich W. H. Kossebau <[email protected]>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef OKTETA_ARRAYCHANGEMETRICS_HPP
#define OKTETA_ARRAYCHANGEMETRICS_HPP
// lib
#include "oktetacore_export.hpp"
#include "size.hpp"
#include "address.hpp"
// Qt
#include <QDataStream>
namespace Okteta {
// TODO: do we need the invalid status?
class OKTETACORE_EXPORT ArrayChangeMetrics
{
friend QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics);
friend QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics);
private:
static constexpr Address InvalidAddress = -1;
public:
enum Type
{
// Insertion,
// Removal,
Replacement,
Swapping,
// Filling,
// Setting,
Invalid
};
public:
[[nodiscard]]
static constexpr ArrayChangeMetrics asReplacement(Address offset, Size removeLength, Size insertLength);
[[nodiscard]]
static constexpr ArrayChangeMetrics asSwapping(Address firstOffset, Address secondOffset, Size secondLength);
public:
ArrayChangeMetrics() = default;
ArrayChangeMetrics(const ArrayChangeMetrics&) = default;
constexpr ArrayChangeMetrics(Type type, Address offset, qint32 secondArgument, qint32 thirdArgument);
~ArrayChangeMetrics() = default;
ArrayChangeMetrics& operator=(const ArrayChangeMetrics&) = default;
public:
[[nodiscard]]
constexpr bool operator==(const ArrayChangeMetrics& other) const;
public:
void revert();
public:
[[nodiscard]]
constexpr int type() const;
[[nodiscard]]
constexpr Address offset() const;
[[nodiscard]]
constexpr bool isValid() const;
public: // Replacement properties
[[nodiscard]]
constexpr Size removeLength() const;
[[nodiscard]]
constexpr Size insertLength() const;
[[nodiscard]]
constexpr Size lengthChange() const;
public: // Swapping properties
[[nodiscard]]
constexpr Size firstLength() const;
[[nodiscard]]
constexpr Address secondStart() const;
[[nodiscard]]
constexpr Address secondEnd() const;
[[nodiscard]]
constexpr Size secondLength() const;
private:
Type mType = Invalid;
Address mOffset = InvalidAddress;
// TODO: how to make the arguments of the size of the largest union member?
union
{
qint32 mSecondArgument = 0;
Size mRemoveLength;
Address mSecondStart;
};
union
{
qint32 mThirdArgument = 0;
Size mInsertLength;
Size mSecondLength;
};
};
inline constexpr ArrayChangeMetrics ArrayChangeMetrics::asReplacement(Address offset, Size removeLength, Size insertLength)
{
return {Replacement, offset, removeLength, insertLength};
}
inline constexpr ArrayChangeMetrics ArrayChangeMetrics::asSwapping(Address firstOffset, Address secondOffset, Size secondLength)
{
return
Q_ASSERT(firstOffset < secondOffset),
ArrayChangeMetrics{Swapping, firstOffset, secondOffset, secondLength};
}
inline constexpr ArrayChangeMetrics::ArrayChangeMetrics(Type type, Address offset, qint32 secondArgument, qint32 thirdArgument)
: mType(type)
, mOffset(offset)
, mSecondArgument(secondArgument)
, mThirdArgument(thirdArgument)
{}
inline constexpr bool ArrayChangeMetrics::operator==(const ArrayChangeMetrics& other) const
{
return mType == other.mType
&& mOffset == other.mOffset
&& mSecondArgument == other.mSecondArgument
&& mThirdArgument == other.mThirdArgument;
}
inline void ArrayChangeMetrics::revert()
{
if (mType == Replacement) {
const Size helper = mInsertLength;
mInsertLength = mRemoveLength;
mRemoveLength = helper;
} else if (mType == Swapping) {
const Size oldSecondLength = mSecondLength;
mSecondLength = firstLength();
mSecondStart = mOffset + oldSecondLength;
}
}
inline constexpr bool ArrayChangeMetrics::isValid() const { return mOffset != InvalidAddress; }
inline constexpr int ArrayChangeMetrics::type() const { return mType; }
inline constexpr Address ArrayChangeMetrics::offset() const { return mOffset; }
inline constexpr Size ArrayChangeMetrics::removeLength() const { return mRemoveLength; }
inline constexpr Size ArrayChangeMetrics::insertLength() const { return mInsertLength; }
inline constexpr Size ArrayChangeMetrics::lengthChange() const { return mInsertLength - mRemoveLength; }
inline constexpr Address ArrayChangeMetrics::secondStart() const { return mSecondStart; }
inline constexpr Address ArrayChangeMetrics::secondEnd() const { return mSecondStart + mSecondLength - 1; }
inline constexpr Size ArrayChangeMetrics::firstLength() const { return mSecondStart - mOffset; }
inline constexpr Size ArrayChangeMetrics::secondLength() const { return mSecondLength; }
QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics);
QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics);
inline QDataStream& operator<<(QDataStream& outStream, const ArrayChangeMetrics& metrics)
{
outStream << metrics.mType << metrics.mOffset << metrics.mSecondArgument << metrics.mThirdArgument;
return outStream;
}
inline QDataStream& operator>>(QDataStream& inStream, ArrayChangeMetrics& metrics)
{
int type;
inStream >> type >> metrics.mOffset >> metrics.mSecondArgument >> metrics.mThirdArgument;
metrics.mType = (ArrayChangeMetrics::Type)type; // TODO: find out how to stream to enum directly
return inStream;
}
}
Q_DECLARE_TYPEINFO(Okteta::ArrayChangeMetrics, Q_MOVABLE_TYPE);
#endif