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