COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
SequenceFixedSize.h
1//
2// Copyright 2015 - 2025 (C). Alex Robenko. All rights reserved.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8#pragma once
9
10#include "comms/Assert.h"
11#include "comms/details/tag.h"
12#include "comms/ErrorStatus.h"
13#include "comms/field/basic/CommonFuncs.h"
14#include "comms/util/detect.h"
16
17#include <cstddef>
18
19namespace comms
20{
21
22namespace field
23{
24
25namespace adapter
26{
27
28template <typename TBase>
29class SequenceFixedSizeBase : public TBase
30{
31 using BaseImpl = TBase;
32
33public:
34 using ValueType = typename BaseImpl::ValueType;
35 using ElementType = typename BaseImpl::ElementType;
36
37 explicit SequenceFixedSizeBase(std::size_t maxSize)
38 : m_fixedSize(maxSize)
39 {
40 }
41
42 SequenceFixedSizeBase(std::size_t maxSize, const ValueType& val)
43 : BaseImpl(val),
44 m_fixedSize(maxSize)
45 {
46 }
47
48 SequenceFixedSizeBase(std::size_t maxSize, ValueType&& val)
49 : BaseImpl(std::move(val)),
50 m_fixedSize(maxSize)
51 {
52 }
53
54 SequenceFixedSizeBase(const SequenceFixedSizeBase&) = default;
55 SequenceFixedSizeBase(SequenceFixedSizeBase&&) = default;
56 SequenceFixedSizeBase& operator=(const SequenceFixedSizeBase&) = default;
57 SequenceFixedSizeBase& operator=(SequenceFixedSizeBase&&) = default;
58
59 std::size_t length() const
60 {
61 auto currSize = BaseImpl::getValue().size();
62 if (currSize == m_fixedSize) {
63 return BaseImpl::length();
64 }
65
66 if (currSize < m_fixedSize) {
67 auto remSize = m_fixedSize - currSize;
68 auto dummyElem = ElementType();
69 return BaseImpl::length() + (remSize * BaseImpl::elementLength(dummyElem));
70 }
71
72 using Tag =
73 typename comms::util::LazyShallowConditional<
74 std::is_integral<ElementType>::value && (sizeof(ElementType) == sizeof(std::uint8_t))
75 >::template Type<
76 HasRawDataTag,
77 HasFieldsTag
78 >;
79
80 return recalcLen(Tag());
81 }
82
83 template <typename TIter>
84 comms::ErrorStatus read(TIter& iter, std::size_t len)
85 {
86 return BaseImpl::readN(m_fixedSize, iter, len);
87 }
88
89 template <typename TIter>
90 void readNoStatus(TIter& iter)
91 {
92 return BaseImpl::readNoStatusN(m_fixedSize, iter);
93 }
94
95 template <typename TIter>
96 comms::ErrorStatus write(TIter& iter, std::size_t len) const
97 {
98 auto writeCount = std::min(BaseImpl::getValue().size(), m_fixedSize);
99 auto es = BaseImpl::writeN(writeCount, iter, len);
100 if (es != comms::ErrorStatus::Success) {
101 return es;
102 }
103
104 auto remCount = m_fixedSize - writeCount;
105 if (remCount == 0) {
106 return es;
107 }
108
109 auto dummyElem = ElementType();
110 while (0 < remCount) {
111 es = BaseImpl::writeElement(dummyElem, iter, len);
112 if (es != ErrorStatus::Success) {
113 break;
114 }
115
116 --remCount;
117 }
118
119 return es;
120 }
121
122 template <typename TIter>
123 void writeNoStatus(TIter& iter) const
124 {
125 auto writeCount = std::min(BaseImpl::getValue().size(), m_fixedSize);
126 BaseImpl::writeNoStatusN(writeCount, iter);
127
128 auto remCount = m_fixedSize - writeCount;
129 if (remCount == 0) {
130 return;
131 }
132
133 auto dummyElem = ElementType();
134 while (0 < remCount) {
135 BaseImpl::writeElementNoStatus(dummyElem, iter);
136 --remCount;
137 }
138 }
139
140 bool valid() const
141 {
142 return BaseImpl::valid() && (BaseImpl::getValue().size() <= m_fixedSize);
143 }
144
145 bool refresh()
146 {
147 if (!BaseImpl::refresh()) {
148 return false;
149 }
150
151 using Tag =
152 typename comms::util::LazyShallowConditional<
153 comms::util::detect::hasResizeFunc<ElementType>()
154 >::template Type<
155 HasResizeTag,
156 NoResizeTag
157 >;
158
159 return doRefresh(Tag());
160 }
161
162private:
163 template <typename... TParams>
164 using HasRawDataTag = comms::details::tag::Tag1<>;
165
166 template <typename... TParams>
167 using HasFieldsTag = comms::details::tag::Tag2<>;
168
169 template <typename... TParams>
170 using HasFixedLengthElemsTag = comms::details::tag::Tag3<>;
171
172 template <typename... TParams>
173 using HasVarLengthElemsTag = comms::details::tag::Tag4<>;
174
175 template <typename... TParams>
176 using HasResizeTag = comms::details::tag::Tag5<>;
177
178 template <typename... TParams>
179 using NoResizeTag = comms::details::tag::Tag6<>;
180
181 template <typename... TParams>
182 std::size_t recalcLen(HasFieldsTag<TParams...>) const
183 {
184 using Tag =
185 typename comms::util::LazyShallowConditional<
186 ElementType::minLength() == ElementType::maxLength()
187 >::template Type<
188 HasFixedLengthElemsTag,
189 HasVarLengthElemsTag
190 >;
191 return recalcLen(Tag());
192 }
193
194 template <typename... TParams>
195 std::size_t recalcLen(HasRawDataTag<TParams...>) const
196 {
197 return m_fixedSize;
198 }
199
200 template <typename... TParams>
201 std::size_t recalcLen(HasFixedLengthElemsTag<TParams...>) const
202 {
203 return m_fixedSize * ElementType::minLength();
204 }
205
206 template <typename... TParams>
207 std::size_t recalcLen(HasVarLengthElemsTag<TParams...>) const
208 {
209 std::size_t result = 0U;
210 auto count = m_fixedSize;
211 for (auto& elem : BaseImpl::getValue()) {
212 if (count == 0U) {
213 break;
214 }
215
216 result += BaseImpl::elementLength(elem);
217 --count;
218 }
219 return result;
220 }
221
222 template <typename... TParams>
223 bool doRefresh(HasResizeTag<TParams...>)
224 {
225 if (BaseImpl::getValue().size() == m_fixedSize) {
226 return false;
227 }
228
229 BaseImpl::value().resize(m_fixedSize);
230 return true;
231 }
232
233 template <typename... TParams>
234 static constexpr bool doRefresh(NoResizeTag<TParams...>)
235 {
236 return false;
237 }
238
239 std::size_t m_fixedSize = 0;
240};
241
242template <std::size_t TSize, typename TBase>
243class SequenceFixedSize : public SequenceFixedSizeBase<TBase>
244{
245 using BaseImpl = SequenceFixedSizeBase<TBase>;
246
247public:
248 using ValueType = typename BaseImpl::ValueType;
249 using ElementType = typename BaseImpl::ElementType;
250
251 explicit SequenceFixedSize()
252 : BaseImpl(TSize)
253 {
254 }
255
256 explicit SequenceFixedSize(const ValueType& val)
257 : BaseImpl(TSize, val)
258 {
259 }
260
261 SequenceFixedSize(ValueType&& val)
262 : BaseImpl(TSize, std::move(val))
263 {
264 }
265
266 SequenceFixedSize(const SequenceFixedSize&) = default;
267 SequenceFixedSize(SequenceFixedSize&&) = default;
268 SequenceFixedSize& operator=(const SequenceFixedSize&) = default;
269 SequenceFixedSize& operator=(SequenceFixedSize&&) = default;
270
271 static constexpr std::size_t minLength()
272 {
273 return BaseImpl::minLength() + BaseImpl::minElementLength() * TSize;
274 }
275
276 static constexpr std::size_t maxLength()
277 {
278 return BaseImpl::minLength() + BaseImpl::maxElementLength() * TSize;
279 }
280};
281
282
283
284
285
286} // namespace adapter
287
288} // namespace field
289
290} // namespace comms
291
292
293
294
This file contains classes required for generic custom assertion functionality.
This file contain definition of error statuses used by comms module.
comms::option::def::SequenceFixedSize< TSize > SequenceFixedSize
Same as comms::option::def::SequenceFixedSize.
Definition options.h:1594
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:17
@ Success
Used to indicate successful outcome of the operation.
STL namespace.
Replacement to some types from standard type_traits.
Various compile-time detection functions of whether specific member functions and/or types exist.