GCC Code Coverage Report


Directory: ./
File: Fw/DataStructures/ArraySetOrMapImpl.hpp
Date: 2026-09-23 21:11:01
Exec Total Coverage
Lines: 95 96 99.0%
Functions: 128 167 76.6%
Branches: 61 80 76.2%

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 1747 ConstIterator(const ArraySetOrMapImpl<KE, VN>& impl) : SetOrMapImplConstIterator<KE, VN>(), m_impl(&impl) {}
46
47 //! Copy constructor
48 5881 ConstIterator(const ConstIterator& it)
49 5881 : SetOrMapImplConstIterator<KE, VN>(), m_impl(it.m_impl), m_index(it.m_index) {}
50
51 //! Destructor
52 3498 ~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 893 bool compareEqual(const ConstIterator& it) const {
64 893 bool result = false;
65
3/4
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 892 times.
✓ Branch 10 taken 1 times.
✗ Branch 11 not taken.
893 if ((this->m_impl == nullptr) && (it.m_impl == nullptr)) {
66 1 result = true;
67
1/2
✓ Branch 8 taken 892 times.
✗ Branch 9 not taken.
892 } else if (this->m_impl == it.m_impl) {
68 892 result |= (this->m_index == it.m_index);
69
3/4
✓ Branch 4 taken 335 times.
✓ Branch 5 taken 557 times.
✓ Branch 10 taken 335 times.
✗ Branch 11 not taken.
892 result |= (!this->isInRange() and !it.isInRange());
70 }
71 893 return result;
72 }
73
74 //! Return the impl kind
75 //! \return The impl kind
76 6185 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 7808 const Entry& getEntry() const override {
81 7808 FW_ASSERT(this->m_impl != nullptr);
82 7808 FW_ASSERT(this->isInRange(), static_cast<FwAssertArgType>(this->m_index),
83 static_cast<FwAssertArgType>(this->m_impl->m_size));
84 7808 return this->m_impl->m_entries[this->m_index];
85 }
86
87 //! Increment operator
88 5028 void increment() override {
89
1/2
✓ Branch 4 taken 5028 times.
✗ Branch 5 not taken.
5028 if (this->isInRange()) {
90 5028 this->m_index++;
91 }
92 5028 }
93
94 //! Check whether the iterator is in range
95 15426 bool isInRange() const override {
96 15426 FW_ASSERT(this->m_impl != nullptr);
97 15426 return this->m_index < this->m_impl->m_size;
98 }
99
100 //! Set the iterator to the end value
101 354 void setToEnd() {
102 354 FW_ASSERT(this->m_impl != nullptr);
103 354 this->m_index = this->m_impl->m_size;
104 354 }
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 190 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 204 ~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 1746 ConstIterator begin() const { return ConstIterator(*this); }
161
162 //! Clear the set or map
163 785 void clear() { this->m_size = 0; }
164
165 //! Get the end iterator
166 354 ConstIterator end() const {
167 354 auto it = begin();
168
1/1
✓ Branch 3 taken 354 times.
354 it.setToEnd();
169 354 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 29194 Success find(const KE& keyOrElement, //!< The key or element
175 VN& valueOrNil //!< The value or Nil
176 ) const {
177 29194 auto status = Success::FAILURE;
178
2/2
✓ Branch 2 taken 1647444 times.
✓ Branch 3 taken 1970 times.
1661518 for (FwSizeType i = 0; i < this->m_size; i++) {
179
1/1
✓ Branch 4 taken 1647444 times.
1658736 const auto& e = this->m_entries[i];
180
6/7
✗ Branch 5 not taken.
✓ Branch 6 taken 68933 times.
✓ Branch 7 taken 1578479 times.
✓ Branch 8 taken 32 times.
✓ Branch 9 taken 58313 times.
✓ Branch 10 taken 10021 times.
✓ Branch 11 taken 48324 times.
1658736 if (e.getKey() == keyOrElement) {
181
1/1
✓ Branch 8 taken 39 times.
26412 valueOrNil = e.getValue();
182 26412 status = Success::SUCCESS;
183 26412 break;
184 }
185 }
186
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 22611 times.
✓ Branch 3 taken 22611 times.
58388 return status;
187 }
188
189 //! Get the capacity of the set or map (max number of entries)
190 //! \return The capacity
191 27613 FwSizeType getCapacity() const { return this->m_entries.getSize(); }
192
193 //! Get the size (number of entries)
194 //! \return The size
195 32238 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 33893 Success insert(const KE& keyOrElement, //!< The key or element
200 const VN& valueOrNil //!< The value or Nil
201 ) {
202 33893 auto status = Success::FAILURE;
203
2/2
✓ Branch 2 taken 6634386 times.
✓ Branch 3 taken 18371 times.
6661571 for (FwSizeType i = 0; i < this->m_size; i++) {
204
1/1
✓ Branch 3 taken 6634386 times.
6640689 auto& e = this->m_entries[i];
205
6/7
✗ Branch 5 not taken.
✓ Branch 6 taken 73529 times.
✓ Branch 7 taken 6560825 times.
✓ Branch 8 taken 32 times.
✓ Branch 9 taken 72993 times.
✓ Branch 10 taken 12475 times.
✓ Branch 11 taken 60550 times.
6640689 if (e.getKey() == keyOrElement) {
206
1/1
✓ Branch 4 taken 11 times.
13011 e.setValueOrNil(valueOrNil);
207 13011 status = Success::SUCCESS;
208 13011 break;
209 }
210 }
211
8/10
✗ Branch 0 not taken.
✓ Branch 1 taken 31382 times.
✓ Branch 2 taken 18371 times.
✓ Branch 3 taken 13011 times.
✓ Branch 8 taken 18371 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 18350 times.
✓ Branch 11 taken 21 times.
✓ Branch 12 taken 18350 times.
✓ Branch 13 taken 13032 times.
33893 if ((status == Success::FAILURE) && (this->m_size < this->getCapacity())) {
212
4/4
✓ Branch 2 taken 102 times.
✓ Branch 8 taken 18248 times.
✓ Branch 10 taken 102 times.
✓ Branch 16 taken 102 times.
20859 this->m_entries[this->m_size] = Entry(keyOrElement, valueOrNil);
213 20859 this->m_size++;
214 20859 status = Success::SUCCESS;
215 }
216
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 31382 times.
✓ Branch 3 taken 31382 times.
67786 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 6486 Success remove(const KE& keyOrElement, //!< The key or element
222 VN& valueOrNil //!< The value or Nil
223 ) {
224 6486 auto status = Success::FAILURE;
225 // Loop over a fixed bound; the loop exits immediately after m_size is modified
226 6486 const FwSizeType size = this->m_size;
227
2/2
✓ Branch 0 taken 7097 times.
✓ Branch 1 taken 1041 times.
13715 for (FwSizeType i = 0; i < size; i++) {
228
3/8
✓ Branch 3 taken 7097 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2968 times.
✓ Branch 12 taken 4129 times.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
12674 if (this->m_entries[i].getKey() == keyOrElement) {
229
1/2
✓ Branch 3 taken 2968 times.
✗ Branch 13 not taken.
5445 valueOrNil = this->m_entries[i].getValue();
230
2/2
✓ Branch 2 taken 1842 times.
✓ Branch 3 taken 1126 times.
5445 if (i < this->m_size - 1) {
231
2/3
✓ Branch 5 taken 1842 times.
✓ Branch 11 taken 1842 times.
✗ Branch 17 not taken.
3554 this->m_entries[i] = this->m_entries[this->m_size - 1];
232 }
233 5445 this->m_size--;
234 5445 status = Success::SUCCESS;
235 5445 break;
236 }
237 }
238
2/3
✗ Branch 0 not taken.
✓ Branch 1 taken 4009 times.
✓ Branch 3 taken 4009 times.
12972 return status;
239 }
240
241 //! Set the backing storage (typed data)
242 //! entries must point to at least capacity elements of type Entry.
243 191 void setStorage(Entry* entries, //!< The entries
244 FwSizeType capacity //!< The capacity
245 ) {
246 191 this->m_entries.setStorage(entries, capacity);
247 191 this->clear();
248 191 }
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