cc_tools_qt
Common Environment for Protocol Analysis.
Loading...
Searching...
No Matches
ToolsFieldCreator.h
1//
2// Copyright 2016 - 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 <memory>
23
24#include "comms/comms.h"
25
26#include "cc_tools_qt/details/ToolsArrayListFieldImpl.h"
27#include "cc_tools_qt/details/ToolsBitfieldFieldImpl.h"
28#include "cc_tools_qt/details/ToolsBitmaskFieldImpl.h"
29#include "cc_tools_qt/details/ToolsBundleFieldImpl.h"
30#include "cc_tools_qt/details/ToolsEnumFieldImpl.h"
31#include "cc_tools_qt/details/ToolsFloatFieldImpl.h"
32#include "cc_tools_qt/details/ToolsIntFieldImpl.h"
33#include "cc_tools_qt/details/ToolsOptionalFieldImpl.h"
34#include "cc_tools_qt/details/ToolsRawDataFieldImpl.h"
35#include "cc_tools_qt/details/ToolsStringFieldImpl.h"
36#include "cc_tools_qt/details/ToolsUnknownFieldImpl.h"
37#include "cc_tools_qt/details/ToolsUnsignedLongFieldImpl.h"
38#include "cc_tools_qt/details/ToolsVariantFieldImpl.h"
39
40#include <vector>
41
42namespace cc_tools_qt
43{
44
45namespace details
46{
47
48class ToolsFieldCreator
49{
50public:
51 using ToolsFieldPtr = cc_tools_qt::ToolsFieldPtr;
52 using FieldsList = std::vector<ToolsFieldPtr>;
53
54 explicit ToolsFieldCreator(FieldsList& fields) : m_fields(fields) {}
55
56 template <typename TField>
57 static ToolsFieldPtr createField(TField& field)
58 {
59 using DecayedField = typename std::decay<decltype(field)>::type;
60 using Tag = typename DecayedField::CommsTag;
61 return createFieldInternal(field, Tag());
62 }
63
64 template <typename TField>
65 void operator()(TField& field)
66 {
67 m_fields.push_back(createField(field));
68 }
69private:
70 using IntValueTag = comms::field::tag::Int;
71 using BitmaskValueTag = comms::field::tag::Bitmask;
72 using EnumValueTag = comms::field::tag::Enum;
73 using StringTag = comms::field::tag::String;
74 using BitfieldTag = comms::field::tag::Bitfield;
75 using OptionalTag = comms::field::tag::Optional;
76 using BundleTag = comms::field::tag::Bundle;
77 using RawDataArrayListTag = comms::field::tag::RawArrayList;
78 using FieldsArrayListTag = comms::field::tag::ArrayList;
79 using FloatValueTag = comms::field::tag::Float;
80 using VariantTag = comms::field::tag::Variant;
81
82 struct RegularIntTag {};
83 struct BigUnsignedTag {};
84
85 class SubfieldsCreateHelper
86 {
87 public:
88 using FieldCreateFunc = std::function <void (ToolsFieldPtr)>;
89 SubfieldsCreateHelper(FieldCreateFunc&& dispatchOp)
90 : m_dispatchOp(std::move(dispatchOp))
91 {
92 }
93
94 template <typename TField>
95 void operator()(TField&& field)
96 {
97 auto fieldWidget =
98 ToolsFieldCreator::createField(std::forward<TField>(field));
99 m_dispatchOp(std::move(fieldWidget));
100 }
101
102 template <std::size_t TIdx, typename TField>
103 void operator()(TField&& field)
104 {
105 return operator()(field);
106 }
107
108 private:
109 FieldCreateFunc m_dispatchOp;
110 };
111
112 template <typename TField>
113 static ToolsFieldPtr createFieldInternal(TField& field, IntValueTag)
114 {
115 using FieldType = std::decay_t<decltype(field)>;
116 using ValueType = typename FieldType::ValueType;
117
118 static_assert(std::is_integral<ValueType>::value,
119 "ValueType is expected to be integral");
120
121 using Tag =
122 std::conditional_t<
123 std::is_signed_v<ValueType> || (sizeof(ValueType) < sizeof(std::uint64_t)),
124 RegularIntTag,
125 BigUnsignedTag
126 >;
127
128 return createFieldInternal(field, Tag());
129 }
130
131 template <typename TField>
132 static ToolsFieldPtr createFieldInternal(TField& field, RegularIntTag)
133 {
134 return makeIntField(field);
135 }
136
137 template <typename TField>
138 static ToolsFieldPtr createFieldInternal(TField& field, BigUnsignedTag)
139 {
140 return makeUnsignedLongField(field);
141 }
142
143 template <typename TField>
144 static ToolsFieldPtr createFieldInternal(TField& field, BitmaskValueTag)
145 {
146 return makeBitmaskField(field);
147 }
148
149 template <typename TField>
150 static ToolsFieldPtr createFieldInternal(TField& field, EnumValueTag)
151 {
152 return makeEnumField(field);
153 }
154
155 template <typename TField>
156 static ToolsFieldPtr createFieldInternal(TField& field, StringTag)
157 {
158 return makeStringField(field);
159 }
160
161 template <typename TField>
162 static ToolsFieldPtr createFieldInternal(TField& field, BitfieldTag)
163 {
164 auto toolsField = makeBitfieldField(field);
165
166 using FieldPtrType = std::decay_t<decltype(toolsField)>;
167 using FieldType = typename FieldPtrType::element_type;
168 using MembersListType = typename FieldType::Members;
169
170 MembersListType subFields;
171 auto& memberFields = field.value();
172 comms::util::tupleForEach(
173 memberFields,
174 SubfieldsCreateHelper(
175 [&subFields](ToolsFieldPtr fieldParam)
176 {
177 subFields.push_back(std::move(fieldParam));
178 }));
179
180 toolsField->setMembers(std::move(subFields));
181 return toolsField;
182 }
183
184 template <typename TField>
185 static ToolsFieldPtr createFieldInternal(TField& field, OptionalTag)
186 {
187 auto toolsField = makeOptionalField(field);
188 auto& wrappedField = field.field();
189 auto wrappedToolsField = createField(wrappedField);
190 toolsField->setField(std::move(wrappedToolsField));
191 return toolsField;
192 }
193
194 template <typename TField>
195 static ToolsFieldPtr createFieldInternal(TField& field, BundleTag)
196 {
197 auto toolsField = makeBundleField(field);
198
199 using FieldPtrType = std::decay_t<decltype(toolsField)>;
200 using FieldType = typename FieldPtrType::element_type;
201 using MemberFieldsList = typename FieldType::Members;
202
203 MemberFieldsList subFields;
204 auto& memberFields = field.value();
205 comms::util::tupleForEach(
206 memberFields,
207 SubfieldsCreateHelper(
208 [&subFields](ToolsFieldPtr fieldParam)
209 {
210 subFields.push_back(std::move(fieldParam));
211 }));
212
213 toolsField->setMembers(std::move(subFields));
214 return toolsField;
215 }
216
217 template <typename TField>
218 static ToolsFieldPtr createFieldInternal(TField& field, RawDataArrayListTag)
219 {
220 return makeRawDataField(field);
221 }
222
223 template <typename TField>
224 static ToolsFieldPtr createFieldInternal(TField& field, FieldsArrayListTag)
225 {
226 using DecayedField = std::decay_t<decltype(field)>;
227 using CollectionType = typename DecayedField::ValueType;
228 using ElementType = typename CollectionType::value_type;
229
230 auto toolsField = makeArrayListField(field);
231 if (toolsField->hasFixedSize()) {
232 toolsField->adjustFixedSize();
233 }
234
235 toolsField->setWrapFieldCallback(
236 [](ElementType& memField) -> ToolsFieldPtr
237 {
238 return ToolsFieldCreator::createField(memField);
239 });
240
241 toolsField->refreshMembers();
242 return toolsField;
243 }
244
245 template <typename TField>
246 static ToolsFieldPtr createFieldInternal(TField& field, FloatValueTag)
247 {
248 return makeFloatField(field);
249 }
250
251 template <typename TField>
252 static ToolsFieldPtr createFieldInternal(TField& field, VariantTag)
253 {
254 auto toolsField = makeVariantField(field);
255
256 toolsField->setMemberCreateCallback(
257 [&field]() -> ToolsFieldPtr
258 {
259 ToolsFieldPtr ptr;
260 if (field.currentFieldValid()) {
261 field.currentFieldExec(
262 SubfieldsCreateHelper(
263 [&ptr](ToolsFieldPtr wrappedToolsField) noexcept
264 {
265 ptr = std::move(wrappedToolsField);
266 }));
267 }
268 return ptr;
269 });
270
271 if (field.currentFieldValid()) {
272 field.currentFieldExec(
273 SubfieldsCreateHelper(
274 [&toolsField](ToolsFieldPtr wrappedToolsField)
275 {
276 toolsField->setCurrent(std::move(wrappedToolsField));
277 }));
278 }
279 else {
280 toolsField->setCurrent(ToolsFieldPtr());
281 }
282
283 return toolsField;
284 }
285
286 template <typename TField, typename TTag>
287 static ToolsFieldPtr createFieldInternal(TField& field, TTag)
288 {
289 return makeUnknownField(field);
290 }
291
292private:
293 FieldsList& m_fields;
294};
295
296} // namespace details
297
298} // namespace cc_tools_qt
299
Main namespace for all classes / functions of the shared library.