cc_tools_qt
Common Environment for Protocol Analysis.
Loading...
Searching...
No Matches
ToolsArrayListFieldImpl.h
1//
2// Copyright 2015 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: GPL-3.0-or-later
5//
6
7// This file is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3 of the License, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20#pragma once
21
22#include "cc_tools_qt/details/ToolsFieldBase.h"
23#include "cc_tools_qt/field/ToolsArrayListField.h"
24
25#include "comms/field/ArrayList.h"
26
27#include <cstdint>
28#include <cassert>
29#include <memory>
30#include <type_traits>
31#include <functional>
32#include <utility>
33
34namespace cc_tools_qt
35{
36
37namespace details
38{
39
40template <typename TField>
41class ToolsArrayListFieldImpl : public ToolsFieldBase<cc_tools_qt::field::ToolsArrayListField, TField>
42{
43 using Base = ToolsFieldBase<cc_tools_qt::field::ToolsArrayListField, TField>;
44 using Field = TField;
45 using ValueType = typename Field::ValueType;
46 using ElementType = typename ValueType::value_type;
47
48public:
49 using SerialisedSeq = typename Base::SerialisedSeq;
50 using Ptr = typename Base::Ptr;
51 using ActPtr = typename Base::ActPtr;
52 using Members = typename Base::Members;
53
54 using WrapFieldCallbackFunc = std::function<ToolsFieldPtr (ElementType&)>;
55
56 explicit ToolsArrayListFieldImpl(Field& fieldRef)
57 : Base(fieldRef)
58 {
59 }
60
61 ToolsArrayListFieldImpl(const ToolsArrayListFieldImpl&) = default;
62 ToolsArrayListFieldImpl(ToolsArrayListFieldImpl&&) = default;
63 virtual ~ToolsArrayListFieldImpl() noexcept = default;
64
65 ToolsArrayListFieldImpl& operator=(const ToolsArrayListFieldImpl&) = delete;
66
67 void setWrapFieldCallback(WrapFieldCallbackFunc&& func)
68 {
69 assert(func);
70 m_wrapFieldFunc = std::move(func);
71 }
72
73protected:
74 virtual bool isHiddenSerializationImpl() const override
75 {
76 static constexpr bool NoPrefix =
77 (!Field::hasElemFixedSerLengthFieldPrefix()) &&
78 (!Field::hasElemSerLengthFieldPrefix()) &&
79 (!Field::hasSerLengthFieldPrefix()) &&
80 (!Field::hasSizeFieldPrefix());
81
82 static constexpr bool NoSuffix =
83 (!Field::hasTerminationFieldSuffix()) &&
84 (!Field::hasTrailingFieldSuffix());
85
86 return NoPrefix && NoSuffix;
87 }
88
89 virtual void addFieldImpl() override
90 {
91 using Tag =
92 std::conditional_t<
93 Field::hasFixedValue(),
94 NoFeatureTag,
95 HasFeatureTag
96 >;
97
98 addFieldInternal(Tag());
99 }
100
101 virtual void removeFieldImpl(int idx) override
102 {
103 using Tag =
104 std::conditional_t<
105 Field::hasFixedValue(),
106 NoFeatureTag,
107 HasFeatureTag
108 >;
109
110 removeFieldInternal(idx, Tag());
111 }
112
113 virtual bool setSerialisedValueImpl([[maybe_unused]] const SerialisedSeq& value) override
114 {
115 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
116 assert(Must_not_be_called);
117 return false;
118 }
119
120 virtual unsigned sizeImpl() const override
121 {
122 return static_cast<unsigned>(Base::field().value().size());
123 }
124
125 virtual bool hasFixedSizeImpl() const override
126 {
127 return Field::hasFixedSize();
128 }
129
130 virtual void adjustFixedSizeImpl() override
131 {
132 using Tag =
133 std::conditional_t<
134 Field::hasFixedValue(),
135 NoFeatureTag,
136 std::conditional_t<
137 Field::hasFixedSize(),
138 HasFixedSizeTag,
139 HasVarSizeTag
140 >
141 >;
142 adjustFixedSizeInternal(Tag());
143 }
144
145 virtual Ptr cloneImpl() override
146 {
147 ActPtr ptr(new ToolsArrayListFieldImpl(Base::field()));
148 static_cast<ToolsArrayListFieldImpl<TField>*>(ptr.get())->m_wrapFieldFunc = m_wrapFieldFunc;
149 return ptr;
150 }
151
152 virtual void refreshMembersImpl() override
153 {
154 using Tag =
155 std::conditional_t<
156 Field::hasFixedValue(),
157 NoFeatureTag,
158 HasFeatureTag
159 >;
160
161 refreshMembersInternal(Tag());
162 }
163
164 virtual void membersUpdatedImpl() override
165 {
166 if (isHiddenSerializationImpl()) {
167 return;
168 }
169
170 auto& mems = Base::getMembers();
171 for (auto& m : mems) {
172 assert(m);
173 m->forceHiddenSerialization();
174 }
175 }
176
177private:
178 struct HasFixedSizeTag {};
179 struct HasVarSizeTag {};
180 struct HasFeatureTag {};
181 struct NoFeatureTag {};
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
264template <typename TField>
265auto makeArrayListField(TField& field)
266{
267 return std::make_unique<ToolsArrayListFieldImpl<TField>>(field);
268}
269
270} // namespace details
271
272} // namespace cc_tools_qt
273
Main namespace for all classes / functions of the shared library.