cc_tools_qt
Common Environment for Protocol Analysis.
Loading...
Searching...
No Matches
ToolsRawDataFieldImpl.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/ToolsRawDataField.h"
24
25#include "comms/field/ArrayList.h"
26
27#include <cstdint>
28#include <cassert>
29#include <memory>
30#include <limits>
31
32namespace cc_tools_qt
33{
34
35namespace details
36{
37
38template <typename TField>
39class ToolsRawDataFieldImpl : public ToolsFieldBase<cc_tools_qt::field::ToolsRawDataField, TField>
40{
41 using Base = ToolsFieldBase<cc_tools_qt::field::ToolsRawDataField, TField>;
42 using Field = TField;
43
44public:
45 using SerialisedSeq = typename Base::SerialisedSeq;
46 using Ptr = typename Base::Ptr;
47 using ActPtr = typename Base::ActPtr;
48
49 explicit ToolsRawDataFieldImpl(Field& fieldRef)
50 : Base(fieldRef)
51 {
52 }
53
54 ToolsRawDataFieldImpl(const ToolsRawDataFieldImpl&) = default;
55 ToolsRawDataFieldImpl(ToolsRawDataFieldImpl&&) = default;
56 virtual ~ToolsRawDataFieldImpl() noexcept = default;
57
58 ToolsRawDataFieldImpl& operator=(const ToolsRawDataFieldImpl&) = delete;
59
60protected:
61
62 virtual QString getValueImpl() const override
63 {
64 QString retStr;
65 auto& dataField = Base::field();
66 auto& data = dataField.value();
67
68 int maxLen = static_cast<int>(Base::length() * 2);
69 if (Base::isTruncated()) {
70 maxLen = static_cast<decltype(maxLen)>(Base::TruncateLength * 2);
71 }
72
73 for (auto byte : data) {
74 if (maxLen <= retStr.size()) {
75 break;
76 }
77
78 retStr.append(QString("%1").arg(static_cast<uint>(byte), 2, 16, QChar('0')));
79 }
80 return retStr;
81 }
82
83 virtual void setValueImpl(const QString& val) override
84 {
85 SerialisedSeq data;
86 QString byteStr;
87
88 auto addByteToData =
89 [&data, &byteStr]() mutable
90 {
91 bool ok = false;
92 auto intVal = byteStr.toInt(&ok, 16);
93 if (!ok) {
94 return;
95 }
96
97 data.push_back(static_cast<typename SerialisedSeq::value_type>(intVal));
98 byteStr.clear();
99 };
100
101 for (auto ch : val) {
102 if (((ch < '0') || ('9' < ch)) &&
103 ((ch.toLower() < 'a') || ('f' < ch.toLower()))) {
104 continue;
105 }
106
107 byteStr.append(ch);
108
109 if (2 <= byteStr.size()) {
110 addByteToData();
111 }
112 }
113
114 if (!byteStr.isEmpty()) {
115 byteStr.append('0');
116 addByteToData();
117 }
118
119 Base::setSerialisedValueImpl(data);
120 }
121
122 virtual SerialisedSeq getSerialisedValueImpl() const override
123 {
124 auto serValue = Base::getSerialisedValueImpl();
125 if (Base::isTruncated()) {
126 serValue.resize(Base::TruncateLength);
127 }
128
129 return serValue;
130 }
131
132 virtual bool setSerialisedValueImpl([[maybe_unused]] const SerialisedSeq& value) override
133 {
134 [[maybe_unused]] static constexpr bool Must_not_be_called = false;
135 assert(Must_not_be_called);
136 return false;
137 }
138
139 virtual int maxSizeImpl() const override
140 {
141 return maxSizeInternal(SizeExistanceTag());
142 }
143
144 virtual int minSizeImpl() const override
145 {
146 return minSizeInternal(SizeExistanceTag());
147 }
148
149 virtual Ptr cloneImpl() override
150 {
151 return ActPtr(new ToolsRawDataFieldImpl<TField>(Base::field()));
152 }
153
154private:
155 struct SizeFieldExistsTag {};
156 struct SerLengthFieldExistsTag {};
157 struct FixedSizeTag {};
158 struct NoLimitsTag {};
159
160 using SizeExistanceTag =
161 std::conditional_t<
162 Field::hasSizeFieldPrefix(),
163 SizeFieldExistsTag,
164 std::conditional_t<
165 Field::hasSerLengthFieldPrefix(),
166 SerLengthFieldExistsTag,
167 std::conditional_t<
168 Field::hasFixedSize(),
169 FixedSizeTag,
170 NoLimitsTag
171 >
172 >
173 >;
174
175 template <typename TPrefixField>
176 static int maxSizeByPrefix()
177 {
178 if (sizeof(int) <= TPrefixField::maxLength()) {
179 return std::numeric_limits<int>::max();
180 }
181
182 auto shift =
183 TPrefixField::maxLength() * std::numeric_limits<std::uint8_t>::digits;
184
185 return static_cast<int>((1U << shift) - 1);
186 }
187
188 static int maxSizeInternal(SizeFieldExistsTag)
189 {
190 using PrefixField = typename Field::SizeFieldPrefix;
191 return maxSizeByPrefix<PrefixField>();
192 }
193
194 static int maxSizeInternal(SerLengthFieldExistsTag)
195 {
196 using PrefixField = typename Field::SerLengthFieldPrefix;
197 return maxSizeByPrefix<PrefixField>();
198 }
199
200 static int maxSizeInternal(FixedSizeTag)
201 {
202 return static_cast<int>(Field::fixedSize());
203 }
204
205 int maxSizeInternal(NoLimitsTag) const
206 {
207 return
208 static_cast<int>(
209 std::min(
210 static_cast<std::size_t>(std::numeric_limits<int>::max()),
211 Base::field().value().max_size()));
212 }
213
214 static int minSizeInternal(SizeFieldExistsTag)
215 {
216 return 0;
217 }
218
219 static int minSizeInternal(SerLengthFieldExistsTag)
220 {
221 return 0;
222 }
223
224 static int minSizeInternal(FixedSizeTag)
225 {
226 return static_cast<int>(Field::fixedSize());
227 }
228
229 int minSizeInternal(NoLimitsTag) const
230 {
231 return 0;
232 }
233};
234
235template <typename TField>
236auto makeRawDataField(TField& field)
237{
238 return std::make_unique<ToolsRawDataFieldImpl<TField>>(field);
239}
240
241} // namespace details
242
243} // namespace cc_tools_qt
244
Main namespace for all classes / functions of the shared library.