cc_tools_qt
Common Environment for Protocol Analysis.
Loading...
Searching...
No Matches
ArrayListWrapper.h
1//
2// Copyright 2015 - 2024 (C). Alex Robenko. All rights reserved.
3//
4
5// This file is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18
19#pragma once
20
21
22#pragma once
23
24#include <cstdint>
25#include <cassert>
26#include <memory>
27#include <type_traits>
28#include <functional>
29#include <utility>
30
31#include "comms/comms.h"
32
33#include "FieldWrapper.h"
34
35namespace cc_tools_qt
36{
37
38namespace field_wrapper
39{
40
41class CC_API ArrayListWrapper : public FieldWrapper
42{
43public:
44
45 typedef std::vector<FieldWrapperPtr> Members;
46 typedef std::unique_ptr<ArrayListWrapper> Ptr;
47
48 ArrayListWrapper();
49 ArrayListWrapper(const ArrayListWrapper&) = delete;
50 ArrayListWrapper& operator=(const ArrayListWrapper&) = delete;
51
52 virtual ~ArrayListWrapper() noexcept;
53
54 void addField();
55
56 void removeField(int idx);
57
58 unsigned size() const;
59
60 bool hasFixedSize() const;
61
62 void adjustFixedSize();
63
64 Members& getMembers();
65
66 const Members& getMembers() const;
67
68 void setMembers(Members&& members);
69
70 Ptr clone();
71
72 void refreshMembers();
73
74 using PrefixFieldInfo = std::pair<int, SerialisedSeq>;
75
76 PrefixFieldInfo getPrefixFieldInfo() const;
77
78protected:
79 virtual void addFieldImpl() = 0;
80 virtual void removeFieldImpl(int idx) = 0;
81 virtual unsigned sizeImpl() const = 0;
82 virtual bool hasFixedSizeImpl() const = 0;
83 virtual void adjustFixedSizeImpl() = 0;
84 virtual Ptr cloneImpl() = 0;
85 virtual void refreshMembersImpl() = 0;
86 virtual PrefixFieldInfo getPrefixFieldInfoImpl() const = 0;
87
88 void dispatchImpl(FieldWrapperHandler& handler);
89
90private:
91 Members m_members;
92};
93
94template <typename TField>
95class ArrayListWrapperT : public FieldWrapperT<ArrayListWrapper, TField>
96{
97 using Base = FieldWrapperT<ArrayListWrapper, TField>;
98 using Field = TField;
99 using ValueType = typename Field::ValueType;
100 using ElementType = typename ValueType::value_type;
101
102public:
103 using SerialisedSeq = typename Base::SerialisedSeq;
104 using Ptr = typename Base::Ptr;
105 using PrefixFieldInfo = typename Base::PrefixFieldInfo;
106
107 typedef std::function<FieldWrapperPtr (ElementType&)> WrapFieldCallbackFunc;
108
109 explicit ArrayListWrapperT(Field& fieldRef)
110 : Base(fieldRef)
111 {
112 }
113
114 ArrayListWrapperT(const ArrayListWrapperT&) = default;
115 ArrayListWrapperT(ArrayListWrapperT&&) = default;
116 virtual ~ArrayListWrapperT() noexcept = default;
117
118 ArrayListWrapperT& operator=(const ArrayListWrapperT&) = delete;
119
120 void setWrapFieldCallback(WrapFieldCallbackFunc&& func)
121 {
122 assert(func);
123 m_wrapFieldFunc = std::move(func);
124 }
125
126protected:
127
128 virtual void addFieldImpl() override
129 {
130 auto& col = Base::field().value();
131
132 auto& mems = Base::getMembers();
133
134 decltype(&col[0]) firstElemPtr = nullptr;
135 if (!col.empty()) {
136 firstElemPtr = &col[0];
137 }
138
139 col.push_back(ElementType());
140 if (!m_wrapFieldFunc) {
141 [[maybe_unused]] static constexpr bool Callback_is_not_set = false;
142 assert(Callback_is_not_set);
143 mems.clear();
144 return;
145 }
146
147 if (firstElemPtr == &col[0]) {
148 mems.push_back(m_wrapFieldFunc(col.back()));
149 assert(col.size() == mems.size());
150 return;
151 }
152
153 mems.clear();
154 mems.reserve(col.size());
155 for (auto& f : col) {
156 mems.push_back(m_wrapFieldFunc(f));
157 }
158
159 assert(col.size() == mems.size());
160 }
161
162 virtual void removeFieldImpl(int idx) override
163 {
164 auto& storage = Base::field().value();
165 if (static_cast<decltype(idx)>(storage.size()) <= idx) {
166 return;
167 }
168
169 storage.erase(storage.begin() + idx);
170 auto& mems = Base::getMembers();
171 mems.clear();
172 mems.reserve(storage.size());
173 for (auto& f : storage) {
174 mems.push_back(m_wrapFieldFunc(f));
175 }
176 }
177
178 virtual bool setSerialisedValueImpl([[maybe_unused]] const SerialisedSeq& value) override
179 {
180 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
181 assert(Must_not_be_called);
182 return false;
183 }
184
185 virtual unsigned sizeImpl() const override
186 {
187 return static_cast<unsigned>(Base::field().value().size());
188 }
189
190 virtual bool hasFixedSizeImpl() const override
191 {
192 return Field::hasFixedSize();
193 }
194
195 virtual void adjustFixedSizeImpl() override
196 {
197 using Tag =
198 typename std::conditional<
199 Field::hasFixedSize(),
200 HasFixedSizeTag,
201 HasVarSizeTag
202 >::type;
203 adjustFixedSizeInternal(Tag());
204 }
205
206 virtual Ptr cloneImpl() override
207 {
208 Ptr ptr(new ArrayListWrapperT(Base::field()));
209 static_cast<ArrayListWrapperT<TField>*>(ptr.get())->m_wrapFieldFunc = m_wrapFieldFunc;
210 return ptr;
211 }
212
213 virtual void refreshMembersImpl() override
214 {
215 if (!m_wrapFieldFunc) {
216 [[maybe_unused]] static constexpr bool Callback_is_not_set = false;
217 assert(Callback_is_not_set);
218 }
219
220 auto& storage = Base::field().value();
221 auto& mems = Base::getMembers();
222 mems.clear();
223 mems.reserve(storage.size());
224 for (auto& f : storage) {
225 mems.push_back(m_wrapFieldFunc(f));
226 if (!mems.back()->canWrite()) {
227 mems.back()->reset();
228 assert(mems.back()->canWrite());
229 }
230 }
231 }
232
233 virtual PrefixFieldInfo getPrefixFieldInfoImpl() const override
234 {
235 using Tag =
236 typename std::conditional<
237 Field::hasSizeFieldPrefix(),
238 ElemCountFieldTag,
239 typename std::conditional<
240 Field::hasSerLengthFieldPrefix(),
241 SerLengthFieldTag,
242 NoPrefixFieldTag
243 >::type
244 >::type;
245
246 return getPrefixFieldInfoInternal(Tag());
247 }
248
249private:
250 struct NoPrefixFieldTag {};
251 struct ElemCountFieldTag {};
252 struct SerLengthFieldTag {};
253 struct SerLengthFieldFixedTag {};
254 struct SerLengthFieldVarTag {};
255 struct HasFixedSizeTag {};
256 struct HasVarSizeTag {};
257
258 PrefixFieldInfo getPrefixFieldInfoInternal(NoPrefixFieldTag) const
259 {
260 return std::make_pair(0, SerialisedSeq());
261 }
262
263 PrefixFieldInfo getPrefixFieldInfoInternal(ElemCountFieldTag) const
264 {
265 using SizeField = typename Field::SizeFieldPrefix;
266 SizeField sizeField;
267 sizeField.setValue(Base::field().value().size());
268 return std::make_pair(static_cast<int>(sizeField.getValue()), getPrefixFieldSerialised(sizeField));
269 }
270
271 PrefixFieldInfo getPrefixFieldInfoInternal(SerLengthFieldTag) const
272 {
273 using LengthField = typename Field::SerLengthFieldPrefix;
274 using Tag =
275 typename std::conditional<
276 LengthField::hasVarLength(),
277 SerLengthFieldVarTag,
278 SerLengthFieldFixedTag
279 >::type;
280
281 return getPrefixFieldInfoInternal(Tag());
282 }
283
284 PrefixFieldInfo getPrefixFieldInfoInternal(SerLengthFieldFixedTag) const
285 {
286 using LengthField = typename Field::SerLengthFieldPrefix;
287 LengthField lenField;
288 lenField.setValue(Base::field().length() - LengthField::maxLength());
289 return std::make_pair(static_cast<int>(lenField.getValue()), getPrefixFieldSerialised(lenField));
290 }
291
292 PrefixFieldInfo getPrefixFieldInfoInternal(SerLengthFieldVarTag) const
293 {
294 using LengthField = typename Field::SerLengthFieldPrefix;
295
296 auto fullLen = Base::field().length();
297 LengthField lenFieldTmp;
298 lenFieldTmp.setValue(fullLen);
299 auto tmpLen = lenFieldTmp.length();
300 LengthField lenField;
301 lenField.setValue(fullLen - tmpLen);
302 if (lenField.length() == tmpLen) {
303 assert(static_cast<int>(lenField.getValue()) <= std::numeric_limits<int>::max());
304 return std::make_pair(static_cast<int>(lenField.getValue()), getPrefixFieldSerialised(lenField));
305 }
306
307 lenField.setValue(fullLen - lenField.length());
308 assert(static_cast<int>(lenField.getValue()) <= std::numeric_limits<int>::max());
309 return std::make_pair(static_cast<int>(lenField.getValue()), getPrefixFieldSerialised(lenField));
310 }
311
312 template <typename TPrefixField>
313 SerialisedSeq getPrefixFieldSerialised(const TPrefixField& prefixField) const
314 {
315 SerialisedSeq serData;
316 serData.reserve(prefixField.length());
317 auto writeIter = std::back_inserter(serData);
318 [[maybe_unused]] auto es = prefixField.write(writeIter, serData.max_size());
319 assert(es == comms::ErrorStatus::Success);
320 return serData;
321 }
322
323 void adjustFixedSizeInternal(HasVarSizeTag)
324 {
325 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
326 assert(Must_not_be_called);
327 }
328
329 void adjustFixedSizeInternal(HasFixedSizeTag)
330 {
331 COMMS_GNU_WARNING_PUSH
332#if defined(NDEBUG) && COMMS_IS_GCC_13 && (COMMS_IS_CPP20)
333 COMMS_GNU_WARNING_DISABLE("-Wstringop-overflow")
334#endif
335
336 Base::field().value().resize(Field::fixedSize());
337 COMMS_GNU_WARNING_POP
338 }
339
340
341 WrapFieldCallbackFunc m_wrapFieldFunc;
342};
343
344using ArrayListWrapperPtr = ArrayListWrapper::Ptr;
345
346template <typename TField>
347ArrayListWrapperPtr
348makeArrayListWrapper(TField& field)
349{
350 return
351 ArrayListWrapperPtr(
352 new ArrayListWrapperT<TField>(field));
353}
354
355template <typename TField>
356std::unique_ptr<ArrayListWrapperT<TField> >
357makeDowncastedArrayListWrapper(TField& field)
358{
359 return
360 std::unique_ptr<ArrayListWrapperT<TField> >(
361 new ArrayListWrapperT<TField>(field));
362}
363
364} // namespace field_wrapper
365
366} // namespace cc_tools_qt
367
368
369
Main namespace for all classes / functions of the shared library.