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