COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
SequenceElemLengthForcing.h
1//
2// Copyright 2017 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
10#pragma once
11
12#include "comms/Assert.h"
13#include "comms/ErrorStatus.h"
14#include "comms/field/basic/CommonFuncs.h"
15
16#include <cstddef>
17#include <iterator>
18#include <limits>
19#include <type_traits>
20#include <utility>
21
22namespace comms
23{
24
25namespace field
26{
27
28namespace adapter
29{
30
31template <typename TBase>
32class SequenceElemLengthForcing : public TBase
33{
34 using BaseImpl = TBase;
35public:
36 using ValueType = typename BaseImpl::ValueType;
37 using ElementType = typename BaseImpl::ElementType;
38
39 SequenceElemLengthForcing() = default;
40
41 explicit SequenceElemLengthForcing(const ValueType& val)
42 : BaseImpl(val)
43 {
44 }
45
46 explicit SequenceElemLengthForcing(ValueType&& val)
47 : BaseImpl(std::move(val))
48 {
49 }
50
51 SequenceElemLengthForcing(const SequenceElemLengthForcing&) = default;
52 SequenceElemLengthForcing(SequenceElemLengthForcing&&) = default;
53 SequenceElemLengthForcing& operator=(const SequenceElemLengthForcing&) = default;
54 SequenceElemLengthForcing& operator=(SequenceElemLengthForcing&&) = default;
55
56 void forceReadElemLength(std::size_t val)
57 {
58 COMMS_ASSERT(val != Cleared);
59 m_forced = val;
60 }
61
62 void clearReadElemLengthForcing()
63 {
64 m_forced = Cleared;
65 }
66
67 std::size_t length() const
68 {
69 if (m_forced != Cleared) {
70 return BaseImpl::getValue().size() * m_forced;
71 }
72
73 return BaseImpl::length();
74 }
75
76 std::size_t elementLength(const ElementType& elem) const
77 {
78 if (m_forced != Cleared) {
79 return m_forced;
80 }
81 return BaseImpl::elementLength(elem);
82 }
83
84 static constexpr std::size_t maxElementLength()
85 {
86 return basic::CommonFuncs::maxSupportedLength();
87 }
88
89 template <typename TIter>
90 ErrorStatus readElement(ElementType& elem, TIter& iter, std::size_t& len) const
91 {
92 using IterType = typename std::decay<decltype(iter)>::type;
93 using IterTag = typename std::iterator_traits<IterType>::iterator_category;
94 static_assert(std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
95 "Only random access iterator for reading is supported with comms::option::def::SequenceElemLengthForcingEnabled option");
96
97 if (m_forced == Cleared) {
98 return BaseImpl::readElement(elem, iter, len);
99 }
100
101 if (len < m_forced) {
103 }
104
105 auto iterTmp = iter;
106 auto remLen = m_forced;
107 std::advance(iter, m_forced);
108 len -= m_forced;
109 return BaseImpl::readElement(elem, iterTmp, remLen);
110 }
111
112 template <typename TIter>
113 void readElementNoStatus(ElementType& elem, TIter& iter) const
114 {
115 using IterType = typename std::decay<decltype(iter)>::type;
116 using IterTag = typename std::iterator_traits<IterType>::iterator_category;
117 static_assert(std::is_base_of<std::random_access_iterator_tag, IterTag>::value,
118 "Only random access iterator for reading is supported with comms::option::def::SequenceElemLengthForcingEnabled option");
119
120 if (m_forced == Cleared) {
121 return BaseImpl::readElementNoStatus(elem, iter);
122 }
123
124 auto fromIter = iter;
125 auto es = BaseImpl::readElementNoStatus(elem, iter);
126 if (es != comms::ErrorStatus::Success) {
127 return es;
128 }
129
130 auto consumed = std::distance(fromIter, iter);
131 if (consumed < m_forced) {
132 std::advance(iter, m_forced - consumed);
133 }
134 }
135
136 template <typename TIter>
137 comms::ErrorStatus read(TIter& iter, std::size_t len)
138 {
139 return basic::CommonFuncs::readSequence(*this, iter, len);
140 }
141
142 static constexpr bool hasReadNoStatus()
143 {
144 return false;
145 }
146
147 template <typename TIter>
148 void readNoStatus(TIter& iter) = delete;
149
150 template <typename TIter>
151 ErrorStatus readN(std::size_t count, TIter& iter, std::size_t& len)
152 {
153 return basic::CommonFuncs::readSequenceN(*this, count, iter, len);
154 }
155
156 template <typename TIter>
157 void readNoStatusN(std::size_t count, TIter& iter) = delete;
158// {
159// basic::CommonFuncs::readSequenceNoStatusN(*this, count, iter);
160// }
161
162private:
163
164 static const std::size_t Cleared = std::numeric_limits<std::size_t>::max();
165 std::size_t m_forced = Cleared;
166};
167
168} // namespace adapter
169
170} // namespace field
171
172} // namespace comms
173
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
This file contain definition of error statuses used by comms module.
Main namespace for all classes / functions of COMMS library.
ErrorStatus
Error statuses reported by the Communication module.
Definition ErrorStatus.h:19
@ Success
Used to indicate successful outcome of the operation.
STL namespace.