@@ -65,6 +65,10 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
6565 // / @brief Type of the field object used to read/write checksum value.
6666 using Field = typename BaseImpl::Field;
6767
68+ // / @brief Type of the escape field provided via @ref comms::option::def::FrameLayerSeekField option.
69+ // / @details Same as @b void if not provided via said option.
70+ using EscField = typename ParsedOptionsInternal::EscField;
71+
6872 // / @brief Default constructor.
6973 SyncSuffixLayer () = default ;
7074
@@ -207,6 +211,18 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
207211 return field == Field ();
208212 }
209213
214+ // / @brief Verify the validity of the escapte field provided via @ref comms::option::def::FrameLayerSeekField option.
215+ // / @details Default implementation compares read field with default constructed type. @n
216+ // / May be overridden by the extending class in case
217+ // / more complex logic is required.
218+ // / @param[out] field Field that has been read.
219+ // / @note May be non-static in the extending class
220+ template <typename TEscField>
221+ static bool verifyEscFieldValue (const TEscField& field)
222+ {
223+ return field == TEscField ();
224+ }
225+
210226 // / @brief Prepare field for writing.
211227 // / @details Default implementation does nothing. @n
212228 // / May be overridden by the extending class in case
@@ -232,6 +248,12 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
232248 template <typename ... TParams>
233249 using VerifyAfterReadTag = comms::details::tag::Tag4<>;
234250
251+ template <typename ... TParams>
252+ using EscapeSupportedTag = comms::details::tag::Tag5<>;
253+
254+ template <typename ... TParams>
255+ using NoEscapeTag = comms::details::tag::Tag6<>;
256+
235257 template <typename TMsg, typename TIter, typename TReader, typename ... TExtraValues>
236258 ErrorStatus verifyRead (
237259 Field& field,
@@ -336,6 +358,7 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
336358 }
337359
338360 if ((fieldEs == ErrorStatus::Success) &&
361+ (!fieldEscapedInternal (fromIter, iter)) &&
339362 (thisObj.verifyFieldValue (field))) {
340363 // Set iter to point after field
341364 iter = iterTmp;
@@ -549,6 +572,65 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
549572 return thisObj.writeField (msgPtr, field, to, remSize);
550573 }
551574
575+ template <typename TIter>
576+ bool fieldEscapedInternal (TIter from, TIter to, NoEscapeTag<>)
577+ {
578+ static_cast <void >(from);
579+ static_cast <void >(to);
580+ return false ;
581+ }
582+
583+ template <typename TIter>
584+ bool fieldEscapedInternal (TIter from, TIter to, EscapeSupportedTag<>)
585+ {
586+ auto dist = static_cast <std::size_t >(std::distance (from, to));
587+ dist = std::min (dist, EscField::maxLength ());
588+ if (dist < EscField::minLength ()) {
589+ return false ;
590+ }
591+
592+ auto & thisObj = BaseImpl::thisLayer ();
593+
594+ auto limitIter = to;
595+ std::advance (limitIter, -static_cast <int >(dist));
596+
597+ auto iter = to;
598+ std::advance (iter, -static_cast <int >(EscField::minLength ()));
599+ while (true ) {
600+ auto iterTmp = iter;
601+ EscField escField;
602+ auto len = static_cast <std::size_t >(std::distance (iterTmp, to));
603+ auto es = escField.read (iterTmp, len);
604+ if ((es == comms::ErrorStatus::Success) &&
605+ (iterTmp == to) &&
606+ (thisObj.verifyEscFieldValue (escField))) {
607+ return true ;
608+ }
609+
610+ if (iter == limitIter) {
611+ break ;
612+ }
613+
614+ std::advance (iter, -1 );
615+ }
616+
617+ return false ;
618+ }
619+
620+ template <typename TIter>
621+ bool fieldEscapedInternal (TIter from, TIter to)
622+ {
623+ using EscTag =
624+ typename comms::util::LazyShallowConditional<
625+ std::is_same<EscField, void >::value
626+ >::template Type<
627+ NoEscapeTag,
628+ EscapeSupportedTag
629+ >;
630+
631+ return fieldEscapedInternal (from, to, EscTag ());
632+ }
633+
552634 static_assert (!(hasVerifyBeforeRead() && hasSeekField()),
553635 " Usage of both comms::option::def::FrameLayerVerifyBeforeRead and comms::option::def::FrameLayerSeekField at the same time are not allowed" );
554636};
0 commit comments