Skip to content

Commit 2c1db6f

Browse files
committed
Supporting comms::option::FrameLayerSeekField option in comms::frame::SyncPrefixLayer class.
1 parent 047ae1e commit 2c1db6f

11 files changed

Lines changed: 279 additions & 45 deletions

doxygen/page_frame.dox

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,30 @@
391391
///
392392
/// } // namespace my_protocol
393393
/// @endcode
394-
/// The comms::frame::SyncPrefixLayer class receives two template parameters.
394+
/// The comms::frame::SyncPrefixLayer class receives at least two template parameters.
395+
///
395396
/// The first one is the type of the @b field, that is responsible to read/write
396397
/// the synchronisation byte(s). Please note the usage of @ref comms::option::def::DefaultNumValue
397398
/// option when defining the @b field type. It insures that the default constructed
398-
/// field will have the required value. @n
399+
/// field will have the required value.
400+
///
399401
/// The second template parameter is the upper layer being wrapped.
400402
///
403+
/// Starting from the third template parameter coming behaviour customization options
404+
/// For example passing extra @ref comms::option::def::FrameLayerSeekField will force
405+
/// the layer to actually seek the required prefix in the input data before continuing.
406+
/// @code
407+
/// using MySyncPrefix =
408+
/// comms::frame::SyncPrefixLayer<
409+
/// SyncField,
410+
/// MyChecksum<TMessage, TInputMessages, TAllocationOptions>,
411+
/// comms::option::def::FrameLayerSeekField
412+
/// >;
413+
/// @endcode
414+
/// Similar to the @ref page_frame_tutorial_checksum the @ref page_frame_tutorial_sync
415+
/// can process the trailing (after message payload) synchronization bytes. However, to
416+
/// process such bytes the @ref comms::frame::SyncSuffixLayer class needs to be used instead.
417+
///
401418
/// @section page_frame_tutorial_transport_value Extra Transport Values
402419
/// Some protocol may use extra values as part of the transport information. Such
403420
/// values may have an influence on how the message payload is read and/or on

include/comms/frame/ChecksumLayer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ namespace frame
4949
/// @ref comms::frame::checksum namespace (`comms/frame/checkum` folder).
5050
/// @tparam TNextLayer Next transport layer in frame.
5151
/// @tparam TOptions Extending functionality options. Supported options are:
52+
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
53+
/// name of the extending class, which can be used to extend existing functionality.
54+
/// See also @ref page_custom_checksum_layer tutorial page.
5255
/// @li @ref comms::option::def::FrameLayerVerifyBeforeRead - By default, the
5356
/// @b ChecksumLayer will invoke @b read operation of inner (wrapped) layers
5457
/// and only if it is successful, it will calculate and verify the
5558
/// checksum value. Usage of @ref comms::option::def::FrameLayerVerifyBeforeRead
5659
/// modifies the default behaviour by forcing the checksum verification
5760
/// prior to invocation of @b read operation in the wrapped layer(s).
58-
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
59-
/// name of the extending class, which can be used to extend existing functionality.
60-
/// See also @ref page_custom_checksum_layer tutorial page.
6161
/// @headerfile comms/frame/ChecksumLayer.h
6262
/// @extends comms::frame::FrameLayerBase
6363
template <typename TField, typename TCalc, typename TNextLayer, typename... TOptions>

include/comms/frame/ChecksumPrefixLayer.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ namespace frame
5050
/// @ref comms::frame::checksum namespace (`comms/frame/checkum` folder).
5151
/// @tparam TNextLayer Next transport layer in frame.
5252
/// @tparam TOptions Extending functionality options. Supported options are:
53+
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
54+
/// name of the extending class, which can be used to extend existing functionality.
55+
/// See also @ref page_custom_checksum_layer tutorial page.
5356
/// @li @ref comms::option::def::FrameLayerVerifyBeforeRead - By default, the
5457
/// @b ChecksumPrefixLayer will invoke @b read operation of inner (wrapped) layers
5558
/// and only if it is successful, it will calculate and verify the
5659
/// checksum value. Usage of @ref comms::option::def::FrameLayerVerifyBeforeRead
5760
/// modifies the default behaviour by forcing the checksum verification
5861
/// prior to invocation of @b read operation in the wrapped layer(s).
59-
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
60-
/// name of the extending class, which can be used to extend existing functionality.
61-
/// See also @ref page_custom_checksum_layer tutorial page.
6262
/// @headerfile comms/frame/ChecksumPrefixLayer.h
6363
/// @extends comms::frame::FrameLayerBase
6464
template <typename TField, typename TCalc, typename TNextLayer, typename... TOptions>

include/comms/frame/SyncPrefixLayer.h

Lines changed: 112 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ namespace frame
3939
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
4040
/// name of the extending class, which can be used to extend existing functionality.
4141
/// See also @ref page_custom_sync_prefix_layer.
42+
/// @li @ref comms::option::def::FrameLayerSeekField - By default, the
43+
/// @b SyncSuffixLayer will invoke @b read operation of inner (wrapped) layers
44+
/// and only if it is successful. Usage of @ref comms::option::def::FrameLayerSeekField
45+
/// modifies the default behaviour by forcing layer to seek the field in the
46+
/// buffer (until the successful read and verification)
47+
/// prior to invocation of @b read operation in the wrapped layer(s).
4248
/// @headerfile comms/frame/SyncPrefixLayer.h
4349
/// @extends comms::frame::FrameLayerBase
4450
template <typename TField, typename TNextLayer, typename... TOptions>
@@ -85,7 +91,7 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
8591
/// the next layer is called.
8692
/// @tparam TMsg Type of the @b msg parameter.
8793
/// @tparam TIter Type of iterator used for reading.
88-
/// @tparam TNextLayerReader next layer reader object type.
94+
/// @tparam TNextLayerReader Next layer reader object type.
8995
/// @param[out] field Field object to read.
9096
/// @param[in, out] msg Reference to smart pointer, that already holds or
9197
/// will hold allocated message object, or reference to actual message
@@ -114,26 +120,23 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
114120
TNextLayerReader&& nextLayerReader,
115121
TExtraValues... extraValues)
116122
{
117-
auto& thisObj = BaseImpl::thisLayer();
118-
auto* msgPtr = BaseImpl::toMsgPtr(msg);
119-
auto beforeReadIter = iter;
120-
121-
auto es = thisObj.doReadField(msgPtr, field, iter, size);
122-
if (es == comms::ErrorStatus::NotEnoughData) {
123-
BaseImpl::updateMissingSize(field, size, extraValues...);
124-
}
125-
126-
if (es != comms::ErrorStatus::Success) {
127-
return es;
128-
}
129-
130-
bool verified = thisObj.verifyFieldValue(field);
131-
if (!verified) {
132-
return comms::ErrorStatus::ProtocolError;
133-
}
123+
using SeekTag =
124+
typename comms::util::LazyShallowConditional<
125+
ParsedOptionsInternal::HasSeekField
126+
>::template Type<
127+
SeekFieldTag,
128+
InstantOpTag
129+
>;
134130

135-
auto fieldLen = static_cast<std::size_t>(std::distance(beforeReadIter, iter));
136-
return nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
131+
return
132+
readInternal(
133+
field,
134+
msg,
135+
iter,
136+
size,
137+
std::forward<TNextLayerReader>(nextLayerReader),
138+
SeekTag(),
139+
extraValues...);
137140
}
138141

139142
/// @brief Customized write functionality, invoked by @ref comms::frame::FrameLayerBase::write() "write()".
@@ -195,6 +198,95 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
195198
{
196199
static_cast<void>(field);
197200
}
201+
202+
private:
203+
template <typename... TParams>
204+
using SeekFieldTag = comms::details::tag::Tag1<>;
205+
206+
template <typename... TParams>
207+
using InstantOpTag = comms::details::tag::Tag2<>;
208+
209+
template <typename TMsg, typename TIter, typename TReader, typename... TExtraValues>
210+
ErrorStatus readInternal(
211+
Field& field,
212+
TMsg& msg,
213+
TIter& iter,
214+
std::size_t size,
215+
TReader&& nextLayerReader,
216+
SeekFieldTag<>,
217+
TExtraValues... extraValues)
218+
{
219+
using IterType = typename std::decay<decltype(iter)>::type;
220+
static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
221+
"The read operation is expected to use random access iterator");
222+
223+
auto& thisObj = BaseImpl::thisLayer();
224+
auto* msgPtr = BaseImpl::toMsgPtr(msg);
225+
226+
auto fromIter = iter;
227+
std::size_t consumed = 0U;
228+
while (consumed < size) {
229+
auto iterTmp = iter;
230+
auto remSize = size - consumed;
231+
232+
auto fieldEs = thisObj.doReadField(msgPtr, field, iterTmp, remSize);
233+
if (fieldEs == ErrorStatus::NotEnoughData) {
234+
BaseImpl::updateMissingSize(field, remSize, extraValues...);
235+
BaseImpl::resetMsg(msg);
236+
return fieldEs;
237+
}
238+
239+
if ((fieldEs == ErrorStatus::Success) &&
240+
(thisObj.verifyFieldValue(field))) {
241+
// Set iter to point after field
242+
iter = iterTmp;
243+
break;
244+
}
245+
246+
++iter;
247+
++consumed;
248+
}
249+
250+
if (size <= consumed) {
251+
// Field hasn't been recognized
252+
return ErrorStatus::NotEnoughData;
253+
}
254+
255+
auto remSize = size - static_cast<std::size_t>(std::distance(fromIter, iter));
256+
return nextLayerReader.read(msg, iter, remSize, extraValues...);
257+
}
258+
259+
template <typename TMsg, typename TIter, typename TReader, typename... TExtraValues>
260+
ErrorStatus readInternal(
261+
Field& field,
262+
TMsg& msg,
263+
TIter& iter,
264+
std::size_t size,
265+
TReader&& nextLayerReader,
266+
InstantOpTag<>,
267+
TExtraValues... extraValues)
268+
{
269+
auto& thisObj = BaseImpl::thisLayer();
270+
auto* msgPtr = BaseImpl::toMsgPtr(msg);
271+
auto beforeReadIter = iter;
272+
273+
auto es = thisObj.doReadField(msgPtr, field, iter, size);
274+
if (es == comms::ErrorStatus::NotEnoughData) {
275+
BaseImpl::updateMissingSize(field, size, extraValues...);
276+
}
277+
278+
if (es != comms::ErrorStatus::Success) {
279+
return es;
280+
}
281+
282+
bool verified = thisObj.verifyFieldValue(field);
283+
if (!verified) {
284+
return comms::ErrorStatus::ProtocolError;
285+
}
286+
287+
auto fieldLen = static_cast<std::size_t>(std::distance(beforeReadIter, iter));
288+
return nextLayerReader.read(msg, iter, size - fieldLen, extraValues...);
289+
}
198290
};
199291

200292
namespace details

include/comms/frame/SyncSuffixLayer.h

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ namespace frame
3939
/// @tparam TField Type of the field that is used as to represent checksum value.
4040
/// @tparam TNextLayer Next transport layer in frame.
4141
/// @tparam TOptions Extending functionality options. Supported options are:
42+
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
43+
/// name of the extending class, which can be used to extend existing functionality.
44+
/// See also @ref page_custom_checksum_layer tutorial page.
4245
/// @li @ref comms::option::def::FrameLayerVerifyBeforeRead - By default, the
4346
/// @b SyncSuffixLayer will invoke @b read operation of inner (wrapped) layers
4447
/// and only if it is successful. Usage of @ref comms::option::def::FrameLayerVerifyBeforeRead
@@ -50,9 +53,6 @@ namespace frame
5053
/// modifies the default behaviour by forcing layer to seek the field in the
5154
/// buffer (until the successful read and verification)
5255
/// prior to invocation of @b read operation in the wrapped layer(s).
53-
/// @li @ref comms::option::ExtendingClass - Use this option to provide a class
54-
/// name of the extending class, which can be used to extend existing functionality.
55-
/// See also @ref page_custom_checksum_layer tutorial page.
5656
/// @headerfile comms/frame/SyncSuffixLayer.h
5757
/// @extends comms::frame::FrameLayerBase
5858
template <typename TField, typename TNextLayer, typename... TOptions>
@@ -144,13 +144,17 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
144144
TNextLayerReader&& nextLayerReader,
145145
TExtraValues... extraValues)
146146
{
147+
std::cout << "!!! " << __FUNCTION__ << ": " << std::hex;
148+
std::copy_n(iter, size, std::ostream_iterator<unsigned>(std::cout, " "));
149+
std::cout << std::dec << std::endl;
150+
147151
using IterType = typename std::decay<decltype(iter)>::type;
148152
static_assert(std::is_same<typename std::iterator_traits<IterType>::iterator_category, std::random_access_iterator_tag>::value,
149153
"The read operation is expected to use random access iterator");
150154

151155
using SeekTag =
152156
typename comms::util::LazyShallowConditional<
153-
ParsedOptionsInternal::HasVerifyBeforeRead
157+
ParsedOptionsInternal::HasSeekField
154158
>::template Type<
155159
SeekFieldTag,
156160
InstantOpTag
@@ -243,6 +247,10 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
243247
TReader&& nextLayerReader,
244248
TExtraValues... extraValues)
245249
{
250+
std::cout << "!!! " << __FUNCTION__ << ": " << std::hex;
251+
std::copy_n(iter, size, std::ostream_iterator<unsigned>(std::cout, " "));
252+
std::cout << std::dec << std::endl;
253+
246254
auto fromIter = iter;
247255
auto* msgPtr = BaseImpl::toMsgPtr(msg);
248256
auto fieldLen = Field::minLength();
@@ -281,6 +289,10 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
281289
TReader&& nextLayerReader,
282290
TExtraValues... extraValues)
283291
{
292+
std::cout << "!!! " << __FUNCTION__ << ": " << std::hex;
293+
std::copy_n(iter, size, std::ostream_iterator<unsigned>(std::cout, " "));
294+
std::cout << std::dec << std::endl;
295+
284296
auto fromIter = iter;
285297

286298
auto es = nextLayerReader.read(msg, iter, size, extraValues...);
@@ -321,6 +333,10 @@ class SyncSuffixLayer : public comms::frame::details::SyncSuffixLayerBase<TField
321333
TReader&& nextLayerReader,
322334
TExtraValues... extraValues)
323335
{
336+
std::cout << "!!! " << __FUNCTION__ << ": " << std::hex;
337+
std::copy_n(iter, size, std::ostream_iterator<unsigned>(std::cout, " "));
338+
std::cout << std::dec << std::endl;
339+
324340
auto& thisObj = BaseImpl::thisLayer();
325341
auto* msgPtr = BaseImpl::toMsgPtr(msg);
326342

include/comms/frame/TransportValueLayer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ namespace frame
4444
/// (accessed via @ref comms::Message::transportFields()).
4545
/// @tparam TNextLayer Next transport layer in frame.
4646
/// @tparam TOptions Extending functionality options. Supported options are:
47-
/// @li @ref comms::option::def::PseudoValue - Mark the handled value to be "pseudo"
48-
/// one, i.e. the field is not getting serialised.
4947
/// @li @ref comms::option::def::ExtendingClass - Use this option to provide a class
5048
/// name of the extending class, which can be used to extend existing functionality.
5149
/// See also @ref page_custom_transport_value_layer tutorial page.
@@ -57,6 +55,8 @@ namespace frame
5755
/// happens when the @ref comms::frame::TransportValueLayer preceeds (wraps)
5856
/// @ref comms::frame::MsgIdLayer and is unable to re-assign the read field value
5957
/// to the message object, because the latter hasn't been created yet.
58+
/// @li @ref comms::option::def::PseudoValue - Mark the handled value to be "pseudo"
59+
/// one, i.e. the field is not getting serialised.
6060
/// @headerfile comms/frame/TransportValueLayer.h
6161
/// @extends comms::frame::FrameLayerBase
6262
template <typename TField, std::size_t TIdx, typename TNextLayer, typename... TOptions>

include/comms/frame/details/SyncPrefixLayerOptionsParser.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class SyncPrefixLayerOptionsParser<>
2626
{
2727
public:
2828
static constexpr bool HasExtendingClass = false;
29+
static constexpr bool HasSeekField = false;
2930

3031
using ExtendingClass = void;
3132

@@ -45,6 +46,14 @@ class SyncPrefixLayerOptionsParser<comms::option::def::ExtendingClass<T>, TOptio
4546
using DefineExtendingClass = ExtendingClass;
4647
};
4748

49+
template <typename... TOptions>
50+
class SyncPrefixLayerOptionsParser<comms::option::def::FrameLayerSeekField, TOptions...> :
51+
public SyncPrefixLayerOptionsParser<TOptions...>
52+
{
53+
public:
54+
static constexpr bool HasSeekField = true;
55+
};
56+
4857
template <typename... TOptions>
4958
class SyncPrefixLayerOptionsParser<
5059
comms::option::app::EmptyOption,

include/comms/frame/details/SyncSuffixLayerOptionsParser.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,6 @@ class SyncSuffixLayerOptionsParser<comms::option::def::ExtendingClass<T>, TOptio
5555
using DefineExtendingClass = ExtendingClass;
5656
};
5757

58-
template <typename... TOptions>
59-
class SyncSuffixLayerOptionsParser<
60-
comms::option::app::EmptyOption,
61-
TOptions...> : public SyncSuffixLayerOptionsParser<TOptions...>
62-
{
63-
};
64-
6558
template <typename... TOptions>
6659
class SyncSuffixLayerOptionsParser<comms::option::def::FrameLayerSeekField, TOptions...> :
6760
public SyncSuffixLayerOptionsParser<TOptions...>
@@ -70,6 +63,13 @@ class SyncSuffixLayerOptionsParser<comms::option::def::FrameLayerSeekField, TOpt
7063
static constexpr bool HasSeekField = true;
7164
};
7265

66+
template <typename... TOptions>
67+
class SyncSuffixLayerOptionsParser<
68+
comms::option::app::EmptyOption,
69+
TOptions...> : public SyncSuffixLayerOptionsParser<TOptions...>
70+
{
71+
};
72+
7373
template <typename... TBundledOptions, typename... TOptions>
7474
class SyncSuffixLayerOptionsParser<
7575
std::tuple<TBundledOptions...>,

0 commit comments

Comments
 (0)