GCC Code Coverage Report


Directory: ./
File: Fw/DataStructures/ArraySetOrMapImpl.hpp
Date: 2026-09-03 21:13:48
Exec Total Coverage
Lines: 95 96 99.0%
Functions: 98 146 67.1%
Branches: 59 80 73.8%

Line Branch Exec Source
1 // ======================================================================
2 // \title ArraySetOrMapImpl
3 // \author bocchino
4 // \brief An array-based implementation of a set or map
5 // ======================================================================
6
7 #ifndef Fw_ArraySetOrMapImpl_HPP
8 #define Fw_ArraySetOrMapImpl_HPP
9
10 #include "Fw/DataStructures/ExternalArray.hpp"
11 #include "Fw/DataStructures/SetOrMapImplConstIterator.hpp"
12 #include "Fw/DataStructures/SetOrMapImplEntry.hpp"
13 #include "Fw/Types/Assert.hpp"
14 #include "Fw/Types/SuccessEnumAc.hpp"
15
16 namespace Fw {
17
18 template <typename KE, typename VN>
19 class ArraySetOrMapImpl final {
20 // ----------------------------------------------------------------------
21 // Friend class for testing
22 // ----------------------------------------------------------------------
23
24 template <typename KK, typename VV>
25 friend class ArraySetOrMapImplTester;
26
27 public:
28 // ----------------------------------------------------------------------
29 // Public types
30 // ----------------------------------------------------------------------
31
32 //! The type of an entry in the set or map
33 using Entry = SetOrMapImplEntry<KE, VN>;
34
35 //! Const iterator
36 class ConstIterator final : public SetOrMapImplConstIterator<KE, VN> {
37 public:
38 using ImplKind = typename SetOrMapImplConstIterator<KE, VN>::ImplKind;
39
40 public:
41 //! Default constructor
42 2 ConstIterator() {}
43
44 //! Constructor providing the implementation
45 1609 ConstIterator(const ArraySetOrMapImpl<KE, VN>& impl) : SetOrMapImplConstIterator<KE, VN>(), m_impl(&impl) {}
46
47 //! Copy constructor
48 5682 ConstIterator(const ConstIterator& it)
49 5682 : SetOrMapImplConstIterator<KE, VN>(), m_impl(it.m_impl), m_index(it.m_index) {}
50
51 //! Destructor
52 3222 ~ConstIterator() override = default;
53
54 public:
55 //! Copy assignment operator
56 ConstIterator& operator=(const ConstIterator& it) {
57 this->m_impl = it.m_impl;
58 this->m_index = it.m_index;
59 return *this;
60 }
61
62 //! Equality comparison operator
63 861 bool compareEqual(const ConstIterator& it) const {
64 861 bool result = false;
65
3/4
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 860 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
861 if ((this->m_impl == nullptr) && (it.m_impl == nullptr)) {
66 1 result = true;
67
1/2
✓ Branch 8 taken 860 times.
✗ Branch 9 not taken.
860 } else if (this->m_impl == it.m_impl) {
68 860 result |= (this->m_index == it.m_index);
69
3/4
✓ Branch 4 taken 322 times.
✓ Branch 5 taken 538 times.
✓ Branch 10 taken 322 times.
✗ Branch 11 not taken.
860 result |= (!this->isInRange() and !it.isInRange());
70 }
71 861 return result;
72 }
73
74 //! Return the impl kind
75 //! \return The impl kind
76 6037 ImplKind implKind() const override { return ImplKind::ARRAY; }
77
78 //! Get the set or map impl entry pointed to by this iterator
79 //! \return The set or map impl entry
80 7677 const Entry& getEntry() const override {
81 7677 FW_ASSERT(this->m_impl != nullptr);
82 7677 FW_ASSERT(this->isInRange(), static_cast<FwAssertArgType>(this->m_index),
83 static_cast<FwAssertArgType>(this->m_impl->m_size));
84 7677 return this->m_impl->m_entries[this->m_index];
85 }
86
87 //! Increment operator
88 4904 void increment() override {
89
1/2
✓ Branch 4 taken 4904 times.
✗ Branch 5 not taken.
4904 if (this->isInRange()) {
90 4904 this->m_index++;
91 }
92 4904 }
93
94 //! Check whether the iterator is in range
95 14914 bool isInRange() const override {
96 14914 FW_ASSERT(this->m_impl != nullptr);
97 14914 return this->m_index < this->m_impl->m_size;
98 }
99
100 //! Set the iterator to the end value
101 336 void setToEnd() {
102 336 FW_ASSERT(this->m_impl != nullptr);
103 336 this->m_index = this->m_impl->m_size;
104 336 }
105
106 private:
107 //! The implementation over which to iterate
108 const ArraySetOrMapImpl<KE, VN>* m_impl = nullptr;
109
110 //! The current iteration index
111 FwSizeType m_index = 0;
112 };
113
114 public:
115 // ----------------------------------------------------------------------
116 // Public constructors and destructors
117 // ----------------------------------------------------------------------
118
119 //! Zero-argument constructor
120 163 ArraySetOrMapImpl() = default;
121
122 //! Constructor providing typed backing storage.
123 //! entries must point to at least capacity elements of type Entry.
124 12 ArraySetOrMapImpl(Entry* entries, //!< The entries
125 FwSizeType capacity //!< The capacity
126 12 ) {
127
1/1
✓ Branch 2 taken 12 times.
12 this->setStorage(entries, capacity);
128 12 }
129
130 //! Constructor providing untyped backing storage.
131 //! data must be aligned according to getByteArrayAlignment().
132 //! data must contain at least getByteArraySize(capacity) bytes.
133 1 ArraySetOrMapImpl(ByteArray data, //!< The data
134 FwSizeType capacity //!< The capacity
135 1 ) {
136
1/1
✓ Branch 2 taken 1 times.
1 this->setStorage(data, capacity);
137 1 }
138
139 //! Copy constructor
140
1/1
✓ Branch 6 taken 1 times.
1 ArraySetOrMapImpl(const ArraySetOrMapImpl<KE, VN>& impl) { *this = impl; }
141
142 //! Destructor
143 177 ~ArraySetOrMapImpl() = default;
144
145 public:
146 // ----------------------------------------------------------------------
147 // Public member functions
148 // ----------------------------------------------------------------------
149
150 //! operator=
151 6 ArraySetOrMapImpl<KE, VN>& operator=(const ArraySetOrMapImpl<KE, VN>& impl) {
152
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if (&impl != this) {
153 6 m_entries = impl.m_entries;
154 6 m_size = impl.m_size;
155 }
156 6 return *this;
157 }
158
159 //! Get the begin iterator
160 1608 ConstIterator begin() const { return ConstIterator(*this); }
161
162 //! Clear the set or map
163 733 void clear() { this->m_size = 0; }
164
165 //! Get the end iterator
166 336 ConstIterator end() const {
167 336 auto it = begin();
168
1/1
✓ Branch 3 taken 336 times.
336 it.setToEnd();
169 336 return it;
170 }
171
172 //! Find a value associated with a key in the map or an element in a set
173 //! \return SUCCESS if the item was found
174 29464 Success find(const KE& keyOrElement, //!< The key or element
175 VN& valueOrNil //!< The value or Nil
176 ) const {
177 29464 auto status = Success::FAILURE;
178
2/2
✓ Branch 2 taken 1648687 times.
✓ Branch 3 taken 2017 times.
1663130 for (FwSizeType i = 0; i < this->m_size; i++) {
179
1/1
✓ Branch 4 taken 1648687 times.
1660280 const auto& e = this->m_entries[i];
180
5/7
✗ Branch 5 not taken.
✓ Branch 6 taken 70399 times.
✓ Branch 7 taken 1578288 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 59689 times.
✓ Branch 10 taken 9992 times.
✓ Branch 11 taken 49697 times.
1660280 if (e.getKey() == keyOrElement) {
181
1/1
✓ Branch 8 taken 39 times.
26614 valueOrNil = e.getValue();
182 26614 status = Success::SUCCESS;
183 26614 break;
184 }
185 }
186
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 22719 times.
✓ Branch 3 taken 22719 times.
58928 return status;
187 }
188
189 //! Get the capacity of the set or map (max number of entries)
190 //! \return The capacity
191 27470 FwSizeType getCapacity() const { return this->m_entries.getSize(); }
192
193 //! Get the size (number of entries)
194 //! \return The size
195 32322 FwSizeType getSize() const { return this->m_size; }
196
197 //! Insert an element in the set or a (key, value) pair in the map
198 //! \return SUCCESS if there is room in the set or map
199 33756 Success insert(const KE& keyOrElement, //!< The key or element
200 const VN& valueOrNil //!< The value or Nil
201 ) {
202 33756 auto status = Success::FAILURE;
203
2/2
✓ Branch 2 taken 6635298 times.
✓ Branch 3 taken 18291 times.
6662403 for (FwSizeType i = 0; i < this->m_size; i++) {
204
1/1
✓ Branch 3 taken 6635298 times.
6641577 auto& e = this->m_entries[i];
205
5/7
✗ Branch 5 not taken.
✓ Branch 6 taken 75030 times.
✓ Branch 7 taken 6560268 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 74570 times.
✓ Branch 10 taken 12470 times.
✓ Branch 11 taken 62100 times.
6641577 if (e.getKey() == keyOrElement) {
206
1/1
✓ Branch 4 taken 11 times.
12930 e.setValueOrNil(valueOrNil);
207 12930 status = Success::SUCCESS;
208 12930 break;
209 }
210 }
211
8/10
✗ Branch 0 not taken.
✓ Branch 1 taken 31221 times.
✓ Branch 2 taken 18291 times.
✓ Branch 3 taken 12930 times.
✓ Branch 8 taken 18291 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18281 times.
✓ Branch 11 taken 10 times.
✓ Branch 12 taken 18281 times.
✓ Branch 13 taken 12940 times.
33756 if ((status == Success::FAILURE) && (this->m_size < this->getCapacity())) {
212
4/4
✓ Branch 2 taken 76 times.
✓ Branch 8 taken 18205 times.
✓ Branch 10 taken 76 times.
✓ Branch 16 taken 76 times.
20814 this->m_entries[this->m_size] = Entry(keyOrElement, valueOrNil);
213 20814 this->m_size++;
214 20814 status = Success::SUCCESS;
215 }
216
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 31221 times.
✓ Branch 3 taken 31221 times.
67512 return status;
217 }
218
219 //! Remove an element from the set or a (key, value) pair from the map
220 //! \return SUCCESS if the key or element was there
221 6618 Success remove(const KE& keyOrElement, //!< The key or element
222 VN& valueOrNil //!< The value or Nil
223 ) {
224 6618 auto status = Success::FAILURE;
225 // Loop over a fixed bound; the loop exits immediately after m_size is modified
226 6618 const FwSizeType size = this->m_size;
227
2/2
✓ Branch 0 taken 7078 times.
✓ Branch 1 taken 1144 times.
13891 for (FwSizeType i = 0; i < size; i++) {
228
3/8
✓ Branch 3 taken 7078 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2972 times.
✓ Branch 12 taken 4106 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
12747 if (this->m_entries[i].getKey() == keyOrElement) {
229
1/2
✓ Branch 3 taken 2972 times.
✗ Branch 13 not taken.
5474 valueOrNil = this->m_entries[i].getValue();
230
2/2
✓ Branch 2 taken 1785 times.
✓ Branch 3 taken 1187 times.
5474 if (i < this->m_size - 1) {
231
2/3
✓ Branch 5 taken 1785 times.
✓ Branch 11 taken 1785 times.
✗ Branch 17 not taken.
3473 this->m_entries[i] = this->m_entries[this->m_size - 1];
232 }
233 5474 this->m_size--;
234 5474 status = Success::SUCCESS;
235 5474 break;
236 }
237 }
238
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 4116 times.
✓ Branch 3 taken 4116 times.
13236 return status;
239 }
240
241 //! Set the backing storage (typed data)
242 //! entries must point to at least capacity elements of type Entry.
243 164 void setStorage(Entry* entries, //!< The entries
244 FwSizeType capacity //!< The capacity
245 ) {
246 164 this->m_entries.setStorage(entries, capacity);
247 164 this->clear();
248 164 }
249
250 //! Set the backing storage (untyped data)
251 //! data must be aligned according to getByteArrayAlignment().
252 //! data must contain at least getByteArraySize(capacity) bytes.
253 3 void setStorage(ByteArray data, //!< The data
254 FwSizeType capacity //!< The capacity
255 ) {
256 3 this->m_entries.setStorage(data, capacity);
257 3 this->clear();
258 3 }
259
260 public:
261 // ----------------------------------------------------------------------
262 // Public static functions
263 // ----------------------------------------------------------------------
264
265 //! Get the alignment of the storage for an ArraySetOrMapImpl
266 //! \return The alignment
267 static constexpr U8 getByteArrayAlignment() { return ExternalArray<Entry>::getByteArrayAlignment(); }
268
269 //! Get the size of the storage for an ExternalArray of the specified capacity,
270 //! as a byte array
271 //! \return The byte array size
272 static constexpr FwSizeType getByteArraySize(FwSizeType capacity //!< The capacity
273 ) {
274 return ExternalArray<Entry>::getByteArraySize(capacity);
275 }
276
277 private:
278 // ----------------------------------------------------------------------
279 // Private member variables
280 // ----------------------------------------------------------------------
281
282 //! The array for storing the set or map entries
283 ExternalArray<Entry> m_entries = {};
284
285 //! The number of entries in the set or map
286 FwSizeType m_size = 0;
287 };
288
289 } // namespace Fw
290
291 #endif
292