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