GCC Code Coverage Report


Directory: ./
File: Fw/DataStructures/ArraySetOrMapImpl.hpp
Date: 2026-09-03 22:12:29
Exec Total Coverage
Lines: 43 77 55.8%
Functions: 27 81 33.3%
Branches: 32 51 62.7%

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 ConstIterator() {}
43
44 //! Constructor providing the implementation
45 ConstIterator(const ArraySetOrMapImpl<KE, VN>& impl) : SetOrMapImplConstIterator<KE, VN>(), m_impl(&impl) {}
46
47 //! Copy constructor
48 ConstIterator(const ConstIterator& it)
49 : SetOrMapImplConstIterator<KE, VN>(), m_impl(it.m_impl), m_index(it.m_index) {}
50
51 //! Destructor
52 ~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 bool compareEqual(const ConstIterator& it) const {
64 bool result = false;
65 if ((this->m_impl == nullptr) && (it.m_impl == nullptr)) {
66 result = true;
67 } else if (this->m_impl == it.m_impl) {
68 result |= (this->m_index == it.m_index);
69 result |= (!this->isInRange() and !it.isInRange());
70 }
71 return result;
72 }
73
74 //! Return the impl kind
75 //! \return The impl kind
76 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 const Entry& getEntry() const override {
81 FW_ASSERT(this->m_impl != nullptr);
82 FW_ASSERT(this->isInRange(), static_cast<FwAssertArgType>(this->m_index),
83 static_cast<FwAssertArgType>(this->m_impl->m_size));
84 return this->m_impl->m_entries[this->m_index];
85 }
86
87 //! Increment operator
88 void increment() override {
89 if (this->isInRange()) {
90 this->m_index++;
91 }
92 }
93
94 //! Check whether the iterator is in range
95 bool isInRange() const override {
96 FW_ASSERT(this->m_impl != nullptr);
97 return this->m_index < this->m_impl->m_size;
98 }
99
100 //! Set the iterator to the end value
101 void setToEnd() {
102 FW_ASSERT(this->m_impl != nullptr);
103 this->m_index = this->m_impl->m_size;
104 }
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 5 ArraySetOrMapImpl() = default;
121
122 //! Constructor providing typed backing storage.
123 //! entries must point to at least capacity elements of type Entry.
124 ArraySetOrMapImpl(Entry* entries, //!< The entries
125 FwSizeType capacity //!< The capacity
126 ) {
127 this->setStorage(entries, capacity);
128 }
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 ArraySetOrMapImpl(ByteArray data, //!< The data
134 FwSizeType capacity //!< The capacity
135 ) {
136 this->setStorage(data, capacity);
137 }
138
139 //! Copy constructor
140 ArraySetOrMapImpl(const ArraySetOrMapImpl<KE, VN>& impl) { *this = impl; }
141
142 //! Destructor
143 5 ~ArraySetOrMapImpl() = default;
144
145 public:
146 // ----------------------------------------------------------------------
147 // Public member functions
148 // ----------------------------------------------------------------------
149
150 //! operator=
151 ArraySetOrMapImpl<KE, VN>& operator=(const ArraySetOrMapImpl<KE, VN>& impl) {
152 if (&impl != this) {
153 m_entries = impl.m_entries;
154 m_size = impl.m_size;
155 }
156 return *this;
157 }
158
159 //! Get the begin iterator
160 ConstIterator begin() const { return ConstIterator(*this); }
161
162 //! Clear the set or map
163 7 void clear() { this->m_size = 0; }
164
165 //! Get the end iterator
166 ConstIterator end() const {
167 auto it = begin();
168 it.setToEnd();
169 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 1265 Success find(const KE& keyOrElement, //!< The key or element
175 VN& valueOrNil //!< The value or Nil
176 ) const {
177 1265 auto status = Success::FAILURE;
178
2/2
✓ Branch 0 taken 1334 times.
✓ Branch 1 taken 455 times.
1789 for (FwSizeType i = 0; i < this->m_size; i++) {
179
1/1
✓ Branch 1 taken 1334 times.
1334 const auto& e = this->m_entries[i];
180
2/2
✓ Branch 1 taken 810 times.
✓ Branch 2 taken 524 times.
1334 if (e.getKey() == keyOrElement) {
181
0/1
✗ Branch 2 not taken.
810 valueOrNil = e.getValue();
182 810 status = Success::SUCCESS;
183 810 break;
184 }
185 }
186
1/1
✓ Branch 1 taken 1265 times.
2530 return status;
187 }
188
189 //! Get the capacity of the set or map (max number of entries)
190 //! \return The capacity
191 153 FwSizeType getCapacity() const { return this->m_entries.getSize(); }
192
193 //! Get the size (number of entries)
194 //! \return The size
195 8 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 963 Success insert(const KE& keyOrElement, //!< The key or element
200 const VN& valueOrNil //!< The value or Nil
201 ) {
202 963 auto status = Success::FAILURE;
203
2/2
✓ Branch 0 taken 1352 times.
✓ Branch 1 taken 153 times.
1505 for (FwSizeType i = 0; i < this->m_size; i++) {
204
1/1
✓ Branch 1 taken 1352 times.
1352 auto& e = this->m_entries[i];
205
2/2
✓ Branch 1 taken 810 times.
✓ Branch 2 taken 542 times.
1352 if (e.getKey() == keyOrElement) {
206
0/1
✗ Branch 1 not taken.
810 e.setValueOrNil(valueOrNil);
207 810 status = Success::SUCCESS;
208 810 break;
209 }
210 }
211
6/7
✓ Branch 0 taken 153 times.
✓ Branch 1 taken 810 times.
✓ Branch 3 taken 153 times.
✓ Branch 5 taken 153 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 153 times.
✓ Branch 8 taken 810 times.
963 if ((status == Success::FAILURE) && (this->m_size < this->getCapacity())) {
212
4/4
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 149 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
153 this->m_entries[this->m_size] = Entry(keyOrElement, valueOrNil);
213 153 this->m_size++;
214 153 status = Success::SUCCESS;
215 }
216
1/1
✓ Branch 1 taken 963 times.
1926 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 145 Success remove(const KE& keyOrElement, //!< The key or element
222 VN& valueOrNil //!< The value or Nil
223 ) {
224 145 auto status = Success::FAILURE;
225 // Loop over a fixed bound; the loop exits immediately after m_size is modified
226 145 const FwSizeType size = this->m_size;
227
1/2
✓ Branch 0 taken 151 times.
✗ Branch 1 not taken.
151 for (FwSizeType i = 0; i < size; i++) {
228
3/3
✓ Branch 1 taken 151 times.
✓ Branch 4 taken 145 times.
✓ Branch 5 taken 6 times.
151 if (this->m_entries[i].getKey() == keyOrElement) {
229
1/2
✓ Branch 1 taken 145 times.
✗ Branch 5 not taken.
145 valueOrNil = this->m_entries[i].getValue();
230
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 140 times.
145 if (i < this->m_size - 1) {
231
2/3
✓ Branch 1 taken 5 times.
✓ Branch 4 taken 5 times.
✗ Branch 7 not taken.
5 this->m_entries[i] = this->m_entries[this->m_size - 1];
232 }
233 145 this->m_size--;
234 145 status = Success::SUCCESS;
235 145 break;
236 }
237 }
238
1/1
✓ Branch 1 taken 145 times.
290 return status;
239 }
240
241 //! Set the backing storage (typed data)
242 //! entries must point to at least capacity elements of type Entry.
243 5 void setStorage(Entry* entries, //!< The entries
244 FwSizeType capacity //!< The capacity
245 ) {
246 5 this->m_entries.setStorage(entries, capacity);
247 5 this->clear();
248 5 }
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 void setStorage(ByteArray data, //!< The data
254 FwSizeType capacity //!< The capacity
255 ) {
256 this->m_entries.setStorage(data, capacity);
257 this->clear();
258 }
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