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