cc_tools_qt
Common Environment for Protocol Analysis.
Loading...
Searching...
No Matches
ToolsArrayListFieldImpl.h
1//
2// Copyright 2015 - 2025 (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#include "cc_tools_qt/details/ToolsFieldBase.h"
22#include "cc_tools_qt/field/ToolsArrayListField.h"
23
24#include "comms/field/ArrayList.h"
25
26#include <cstdint>
27#include <cassert>
28#include <memory>
29#include <type_traits>
30#include <functional>
31#include <utility>
32
33namespace cc_tools_qt
34{
35
36namespace details
37{
38
39template <typename TField>
40class ToolsArrayListFieldImpl : public ToolsFieldBase<cc_tools_qt::field::ToolsArrayListField, TField>
41{
42 using Base = ToolsFieldBase<cc_tools_qt::field::ToolsArrayListField, TField>;
43 using Field = TField;
44 using ValueType = typename Field::ValueType;
45 using ElementType = typename ValueType::value_type;
46
47public:
48 using SerialisedSeq = typename Base::SerialisedSeq;
49 using Ptr = typename Base::Ptr;
50 using ActPtr = typename Base::ActPtr;
51 using Members = typename Base::Members;
52
53 using WrapFieldCallbackFunc = std::function<ToolsFieldPtr (ElementType&)>;
54
55 explicit ToolsArrayListFieldImpl(Field& fieldRef)
56 : Base(fieldRef)
57 {
58 }
59
60 ToolsArrayListFieldImpl(const ToolsArrayListFieldImpl&) = default;
61 ToolsArrayListFieldImpl(ToolsArrayListFieldImpl&&) = default;
62 virtual ~ToolsArrayListFieldImpl() noexcept = default;
63
64 ToolsArrayListFieldImpl& operator=(const ToolsArrayListFieldImpl&) = delete;
65
66 void setWrapFieldCallback(WrapFieldCallbackFunc&& func)
67 {
68 assert(func);
69 m_wrapFieldFunc = std::move(func);
70 }
71
72protected:
73 virtual bool isHiddenSerializationImpl() const override
74 {
75 static constexpr bool NoPrefix =
76 (!Field::hasElemFixedSerLengthFieldPrefix()) &&
77 (!Field::hasElemSerLengthFieldPrefix()) &&
78 (!Field::hasSerLengthFieldPrefix()) &&
79 (!Field::hasSizeFieldPrefix());
80
81 static constexpr bool NoSuffix =
82 (!Field::hasTerminationFieldSuffix()) &&
83 (!Field::hasTrailingFieldSuffix());
84
85 return NoPrefix && NoSuffix;
86 }
87
88 virtual void addFieldImpl() override
89 {
90 using Tag =
91 std::conditional_t<
92 Field::hasFixedValue(),
93 NoFeatureTag,
94 HasFeatureTag
95 >;
96
97 addFieldInternal(Tag());
98 }
99
100 virtual void removeFieldImpl(int idx) override
101 {
102 using Tag =
103 std::conditional_t<
104 Field::hasFixedValue(),
105 NoFeatureTag,
106 HasFeatureTag
107 >;
108
109 removeFieldInternal(idx, Tag());
110 }
111
112 virtual bool setSerialisedValueImpl([[maybe_unused]] const SerialisedSeq& value) override
113 {
114 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
115 assert(Must_not_be_called);
116 return false;
117 }
118
119 virtual unsigned sizeImpl() const override
120 {
121 return static_cast<unsigned>(Base::field().value().size());
122 }
123
124 virtual bool hasFixedSizeImpl() const override
125 {
126 return Field::hasFixedSize();
127 }
128
129 virtual void adjustFixedSizeImpl() override
130 {
131 using Tag =
132 std::conditional_t<
133 Field::hasFixedValue(),
134 NoFeatureTag,
135 std::conditional_t<
136 Field::hasFixedSize(),
137 HasFixedSizeTag,
138 HasVarSizeTag
139 >
140 >;
141 adjustFixedSizeInternal(Tag());
142 }
143
144 virtual Ptr cloneImpl() override
145 {
146 ActPtr ptr(new ToolsArrayListFieldImpl(Base::field()));
147 static_cast<ToolsArrayListFieldImpl<TField>*>(ptr.get())->m_wrapFieldFunc = m_wrapFieldFunc;
148 return ptr;
149 }
150
151 virtual void refreshMembersImpl() override
152 {
153 using Tag =
154 std::conditional_t<
155 Field::hasFixedValue(),
156 NoFeatureTag,
157 HasFeatureTag
158 >;
159
160 refreshMembersInternal(Tag());
161 }
162
163 virtual void membersUpdatedImpl() override
164 {
165 if (isHiddenSerializationImpl()) {
166 return;
167 }
168
169 auto& mems = Base::getMembers();
170 for (auto& m : mems) {
171 assert(m);
172 m->forceHiddenSerialization();
173 }
174 }
175
176private:
177 struct HasFixedSizeTag {};
178 struct HasVarSizeTag {};
179 struct HasFeatureTag {};
180 struct NoFeatureTag {};
181
182
183 void adjustFixedSizeInternal(HasVarSizeTag)
184 {
185 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
186 assert(Must_not_be_called);
187 }
188
189 void adjustFixedSizeInternal(HasFixedSizeTag)
190 {
191 COMMS_GNU_WARNING_PUSH
192#if defined(NDEBUG) && COMMS_IS_GCC_13 && (COMMS_IS_CPP20)
193 COMMS_GNU_WARNING_DISABLE("-Wstringop-overflow")
194#endif
195
196 Base::field().value().resize(Field::fixedSize());
197 COMMS_GNU_WARNING_POP
198 }
199
200 void adjustFixedSizeInternal(NoFeatureTag)
201 {
202 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
203 assert(Must_not_be_called);
204 }
205
206 void addFieldInternal(HasFeatureTag)
207 {
208 auto& col = Base::field().value();
209 col.push_back(ElementType());
210 refreshMembersInternal(HasFeatureTag());
211 }
212
213 void addFieldInternal(NoFeatureTag)
214 {
215 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
216 assert(Must_not_be_called);
217 }
218
219 void removeFieldInternal(int idx, HasFeatureTag)
220 {
221 auto& storage = Base::field().value();
222 if (static_cast<decltype(idx)>(storage.size()) <= idx) {
223 return;
224 }
225
226 storage.erase(storage.begin() + idx);
227 refreshMembersInternal(HasFeatureTag());
228 }
229
230 void removeFieldInternal([[maybe_unused]] int idx, NoFeatureTag)
231 {
232 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
233 assert(Must_not_be_called);
234 }
235
236 void refreshMembersInternal(HasFeatureTag)
237 {
238 if (!m_wrapFieldFunc) {
239 [[maybe_unused]] static constexpr bool Callback_is_not_set = false;
240 assert(Callback_is_not_set);
241 }
242
243 auto& storage = Base::field().value();
244 Members mems;
245 mems.reserve(storage.size());
246 for (auto& f : storage) {
247 mems.push_back(m_wrapFieldFunc(f));
248 if (!mems.back()->canWrite()) {
249 mems.back()->reset();
250 assert(mems.back()->canWrite());
251 }
252 }
253
254 Base::setMembers(std::move(mems));
255 }
256
257 void refreshMembersInternal(NoFeatureTag)
258 {
259 }
260
261 WrapFieldCallbackFunc m_wrapFieldFunc;
262};
263
264
265template <typename TField>
266auto makeArrayListField(TField& field)
267{
268 return std::make_unique<ToolsArrayListFieldImpl<TField>>(field);
269}
270
271} // namespace details
272
273} // namespace cc_tools_qt
274
275
276
Main namespace for all classes / functions of the shared library.