Skip to content

Commit 34b7724

Browse files
committed
Supporting escape field when using comms::option::def::FrameLayerSeekField with SyncSuffixLayer.
1 parent 2f35b55 commit 34b7724

4 files changed

Lines changed: 130 additions & 4 deletions

File tree

include/comms/frame/SyncPrefixLayer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,10 +325,10 @@ class SyncPrefixLayer : public comms::frame::details::SyncPrefixLayerBase<TField
325325
auto& thisObj = BaseImpl::thisLayer();
326326

327327
auto limitIter = to;
328-
std::advance(limitIter, -dist);
328+
std::advance(limitIter, -static_cast<int>(dist));
329329

330330
auto iter = to;
331-
std::advance(iter, -EscField::minLength());
331+
std::advance(iter, -static_cast<int>(EscField::minLength()));
332332
while (true) {
333333
auto iterTmp = iter;
334334
EscField escField;

include/comms/frame/SyncSuffixLayer.h

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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
};

test/CommsTestCommon.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,13 +962,11 @@ class CountHandler
962962
template <typename TMsg>
963963
void handle(TMsg&)
964964
{
965-
//std::cout << "Dispatching actual type!!!" << std::endl;
966965
++m_custom;
967966
}
968967

969968
void handle(TMsgBase&)
970969
{
971-
//std::cout << "Dispatching base!!!" << std::endl;
972970
++m_base;
973971
}
974972

test/SyncSuffixLayer.th

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ public:
2323
void test1();
2424
void test2();
2525
void test3();
26+
void test4();
2627

2728
private:
2829

@@ -48,6 +49,20 @@ private:
4849
comms::option::DefaultNumValue<0xabcd>
4950
>;
5051

52+
using BeSyncField2 =
53+
comms::field::IntValue<
54+
BeField,
55+
std::uint16_t,
56+
comms::option::DefaultNumValue<0x3d3d> // ==
57+
>;
58+
59+
using BeEscField =
60+
comms::field::IntValue<
61+
BeField,
62+
std::uint16_t,
63+
comms::option::DefaultNumValue<0x4040> // @@
64+
>;
65+
5166
using BeSizeField =
5267
comms::field::IntValue<
5368
BeField,
@@ -101,6 +116,18 @@ private:
101116
>,
102117
comms::option::def::FrameLayerSeekField<>
103118
>;
119+
120+
using SeekFieldWithEscFrame =
121+
comms::frame::SyncSuffixLayer<
122+
BeSyncField2,
123+
comms::frame::MsgIdLayer<
124+
BeIdField,
125+
BeMsgBase,
126+
AllTestMessages<BeMsgBase>,
127+
comms::frame::MsgDataLayer<>
128+
>,
129+
comms::option::def::FrameLayerSeekField<BeEscField>
130+
>;
104131
};
105132

106133
void SyncSuffixLayerTestSuite::test1()
@@ -154,3 +181,22 @@ void SyncSuffixLayerTestSuite::test3()
154181
TS_ASSERT_EQUALS(std::get<0>(msg11.fields()).value(), "hello");
155182
}
156183

184+
void SyncSuffixLayerTestSuite::test4()
185+
{
186+
static const char Buf[] = {
187+
MessageType11, 'h', 'e', '@', '@', '=', '=', 'l', 'l', 'o', '=', '=', static_cast<char>(0x3f)
188+
};
189+
190+
static const std::size_t BufSize = std::extent<decltype(Buf)>::value;
191+
192+
SeekFieldWithEscFrame frame;
193+
SeekFieldWithEscFrame::MsgPtr msg;
194+
auto readIter = comms::readIteratorFor(msg, Buf);
195+
auto es = frame.read(msg, readIter, BufSize);
196+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
197+
TS_ASSERT(msg);
198+
TS_ASSERT_EQUALS(msg->getId(), MessageType11);
199+
auto& msg11 = dynamic_cast<BeMsg11&>(*msg);
200+
TS_ASSERT_EQUALS(std::get<0>(msg11.fields()).value(), "he@@==llo");
201+
}
202+

0 commit comments

Comments
 (0)