52class SyncPrefixLayer :
public comms::frame::details::SyncPrefixLayerBase<TField, TNextLayer, TOptions...>
54 using BaseImpl = comms::frame::details::SyncPrefixLayerBase<TField, TNextLayer, TOptions...>;
55 using ParsedOptionsInternal = comms::frame::details::SyncPrefixLayerOptionsParser<TOptions...>;
59 using Field =
typename BaseImpl::Field;
63 using EscField =
typename ParsedOptionsInternal::EscField;
79 static constexpr
bool hasExtendingClass()
81 return ParsedOptionsInternal::HasExtendingClass;
112 template <
typename TMsg,
typename TIter,
typename TNextLayerReader,
typename... TExtraValues>
118 TNextLayerReader&& nextLayerReader,
119 TExtraValues... extraValues)
122 typename comms::util::LazyShallowConditional<
123 ParsedOptionsInternal::HasSeekField
135 std::forward<TNextLayerReader>(nextLayerReader),
157 template <
typename TMsg,
typename TIter,
typename TNextLayerWriter>
163 TNextLayerWriter&& nextLayerWriter)
const
165 auto& thisObj = BaseImpl::thisLayer();
166 thisObj.prepareFieldForWrite(field);
167 auto es = thisObj.doWriteField(&msg, field, iter, size);
168 if (es != ErrorStatus::Success) {
173 return nextLayerWriter.write(msg, iter, size - field.length());
185 return field ==
Field();
194 template <
typename TEscField>
197 return field == TEscField();
209 static_cast<void>(field);
213 template <
typename... TParams>
214 using SeekFieldTag = comms::details::tag::Tag1<>;
216 template <
typename... TParams>
217 using InstantOpTag = comms::details::tag::Tag2<>;
219 template <
typename... TParams>
220 using EscapeSupportedTag = comms::details::tag::Tag3<>;
222 template <
typename... TParams>
223 using NoEscapeTag = comms::details::tag::Tag4<>;
225 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
231 TReader&& nextLayerReader,
233 TExtraValues... extraValues)
235 using IterType =
typename std::decay<
decltype(iter)>::type;
236 static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
237 "The read operation is expected to use random access iterator");
239 auto& thisObj = BaseImpl::thisLayer();
240 auto* msgPtr = BaseImpl::toMsgPtr(msg);
242 auto fromIter = iter;
243 std::size_t consumed = 0U;
244 while (consumed < size) {
246 auto remSize = size - consumed;
248 auto fieldEs = thisObj.doReadField(msgPtr, field, iterTmp, remSize);
249 if (fieldEs == ErrorStatus::NotEnoughData) {
250 BaseImpl::updateMissingSize(field, remSize, extraValues...);
251 BaseImpl::resetMsg(msg);
255 if ((fieldEs == ErrorStatus::Success) &&
256 (!fieldEscapedInternal(fromIter, iter)) &&
257 (thisObj.verifyFieldValue(field))) {
267 if (size <= consumed) {
269 return ErrorStatus::NotEnoughData;
272 auto remSize = size -
static_cast<std::size_t
>(std::distance(fromIter, iter));
273 return nextLayerReader.read(msg, iter, remSize, extraValues...);
276 template <
typename TMsg,
typename TIter,
typename TReader,
typename... TExtraValues>
282 TReader&& nextLayerReader,
284 TExtraValues... extraValues)
286 auto& thisObj = BaseImpl::thisLayer();
287 auto* msgPtr = BaseImpl::toMsgPtr(msg);
288 auto beforeReadIter = iter;
290 auto es = thisObj.doReadField(msgPtr, field, iter, size);
292 BaseImpl::updateMissingSize(field, size, extraValues...);
299 bool verified = thisObj.verifyFieldValue(field);
304 auto fieldLen =
static_cast<std::size_t
>(std::distance(beforeReadIter, iter));
305 return nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
308 template <
typename TIter>
309 bool fieldEscapedInternal(TIter from, TIter to, NoEscapeTag<>)
311 static_cast<void>(from);
312 static_cast<void>(to);
316 template <
typename TIter>
317 bool fieldEscapedInternal(TIter from, TIter to, EscapeSupportedTag<>)
319 unsigned escCount = 0U;
320 auto& thisObj = BaseImpl::thisLayer();
323 auto dist =
static_cast<std::size_t
>(std::distance(from, to));
324 dist = std::min(dist, EscField::maxLength());
325 if (dist < EscField::minLength()) {
329 auto maxLenIter = to;
330 std::advance(maxLenIter, -
static_cast<int>(dist));
333 std::advance(iter, -
static_cast<int>(EscField::minLength()));
334 auto prevCount = escCount;
338 auto len =
static_cast<std::size_t
>(std::distance(iterTmp, to));
339 auto es = escField.read(iterTmp, len);
342 (thisObj.verifyEscFieldValue(escField))) {
347 if (iter == maxLenIter) {
351 std::advance(iter, -1);
354 if (prevCount == escCount) {
364 return (escCount & 0x1) != 0U;
367 template <
typename TIter>
368 bool fieldEscapedInternal(TIter from, TIter to)
371 typename comms::util::LazyShallowConditional<
372 std::is_same<EscField, void>::value
378 return fieldEscapedInternal(from, to, EscTag());
comms::ErrorStatus doRead(Field &field, TMsg &msg, TIter &iter, std::size_t size, TNextLayerReader &&nextLayerReader, TExtraValues... extraValues)
Customized read functionality, invoked by read().
Definition SyncPrefixLayer.h:113