1414#include " comms/frame/details/SyncPrefixLayerBase.h"
1515#include " comms/frame/details/SyncPrefixLayerOptionsParser.h"
1616
17+ #include < algorithm>
1718#include < iterator>
1819
1920COMMS_MSVC_WARNING_PUSH
@@ -57,6 +58,10 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
5758 // / @brief Type of the field object used to read/write "sync" value.
5859 using Field = typename BaseImpl::Field;
5960
61+ // / @brief Type of the escape field provided via @ref comms::option::def::FrameLayerSeekField option.
62+ // / @details Same as @b void if not provided via said option.
63+ using EscField = typename ParsedOptionsInternal::EscField;
64+
6065 // / @brief Default constructor
6166 SyncPrefixLayer () = default ;
6267
@@ -180,6 +185,18 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
180185 return field == Field ();
181186 }
182187
188+ // / @brief Verify the validity of the escapte field provided via @ref comms::option::def::FrameLayerSeekField option.
189+ // / @details Default implementation compares read field with default constructed type. @n
190+ // / May be overridden by the extending class in case
191+ // / more complex logic is required.
192+ // / @param[out] field Field that has been read.
193+ // / @note May be non-static in the extending class
194+ template <typename TEscField>
195+ static bool verifyEscFieldValue (const TEscField& field)
196+ {
197+ return field == TEscField ();
198+ }
199+
183200 // / @brief Prepare field for writing.
184201 // / @details Default implementation does nothing. @n
185202 // / May be overridden by the extending class in case
@@ -199,6 +216,12 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
199216 template <typename ... TParams>
200217 using InstantOpTag = comms::details::tag::Tag2<>;
201218
219+ template <typename ... TParams>
220+ using EscapeSupportedTag = comms::details::tag::Tag3<>;
221+
222+ template <typename ... TParams>
223+ using NoEscapeTag = comms::details::tag::Tag4<>;
224+
202225 template <typename TMsg, typename TIter, typename TReader, typename ... TExtraValues>
203226 ErrorStatus readInternal (
204227 Field& field,
@@ -230,6 +253,7 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
230253 }
231254
232255 if ((fieldEs == ErrorStatus::Success) &&
256+ (!fieldEscapedInternal (fromIter, iter)) &&
233257 (thisObj.verifyFieldValue (field))) {
234258 // Set iter to point after field
235259 iter = iterTmp;
@@ -280,6 +304,65 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
280304 auto fieldLen = static_cast <std::size_t >(std::distance (beforeReadIter, iter));
281305 return nextLayerReader.read (msg, iter, size - fieldLen, extraValues...);
282306 }
307+
308+ template <typename TIter>
309+ bool fieldEscapedInternal (TIter from, TIter to, NoEscapeTag<>)
310+ {
311+ static_cast <void >(from);
312+ static_cast <void >(to);
313+ return false ;
314+ }
315+
316+ template <typename TIter>
317+ bool fieldEscapedInternal (TIter from, TIter to, EscapeSupportedTag<>)
318+ {
319+ auto dist = static_cast <std::size_t >(std::distance (from, to));
320+ dist = std::min (dist, EscField::maxLength ());
321+ if (dist < EscField::minLength ()) {
322+ return false ;
323+ }
324+
325+ auto & thisObj = BaseImpl::thisLayer ();
326+
327+ auto limitIter = to;
328+ std::advance (limitIter, -dist);
329+
330+ auto iter = to;
331+ std::advance (iter, -EscField::minLength ());
332+ while (true ) {
333+ auto iterTmp = iter;
334+ EscField escField;
335+ auto len = static_cast <std::size_t >(std::distance (iterTmp, to));
336+ auto es = escField.read (iterTmp, len);
337+ if ((es == comms::ErrorStatus::Success) &&
338+ (iterTmp == to) &&
339+ (thisObj.verifyEscFieldValue (escField))) {
340+ return true ;
341+ }
342+
343+ if (iter == limitIter) {
344+ break ;
345+ }
346+
347+ std::advance (iter, -1 );
348+ }
349+
350+ return false ;
351+ }
352+
353+ template <typename TIter>
354+ bool fieldEscapedInternal (TIter from, TIter to)
355+ {
356+ using EscTag =
357+ typename comms::util::LazyShallowConditional<
358+ std::is_same<EscField, void >::value
359+ >::template Type<
360+ NoEscapeTag,
361+ EscapeSupportedTag
362+ >;
363+
364+ return fieldEscapedInternal (from, to, EscTag ());
365+ }
283366};
284367
285368namespace details
0 commit comments