Skip to content

Commit 2e5b8c8

Browse files
committed
Proper ordering of suffix frame layer.
1 parent 9d1d4b9 commit 2e5b8c8

14 files changed

Lines changed: 336 additions & 33 deletions

File tree

app/commsdsl2comms/test/test55/test55Test.th

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,6 @@ public:
1717
void test1();
1818
void test2();
1919

20-
struct Handler
21-
{
22-
template <typename TMsg>
23-
void handle(TMsg& msg)
24-
{
25-
static_cast<void>(msg);
26-
}
27-
};
28-
2920
using WrapInterface = test55::wrap::Message<>;
3021
using WrapFrame = test55::wrap::frame::WrapFrame<WrapInterface>;
3122

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<schema name="test56" endian="big">
3+
<description>
4+
Testing sync suffix layer together with checksum
5+
</description>
6+
<fields>
7+
<enum name="MsgId" type="uint8" semanticType="messageId" >
8+
<validValue name="M1" val="0" />
9+
<validValue name="M2" val="1" />
10+
</enum>
11+
</fields>
12+
13+
<message name="Msg1" id="MsgId.M1">
14+
<data name="F1" />
15+
</message>
16+
17+
<message name="Msg2" id="MsgId.M2">
18+
<string name="F1" />
19+
</message>
20+
21+
<frame name="Frame">
22+
<sync name="Prefix">
23+
<int name="PrefixField" type="uint16" defaultValue="0x3d3d" />
24+
</sync>
25+
<id name="Id" field="MsgId" />
26+
<payload name="Data" />
27+
<sync name="Suffix" from="Data" seekField="true">
28+
<int name="SuffixField" type="uint16" defaultValue="0x4040" />
29+
</sync>
30+
<checksum name="Checksum" from="Data" alg="sum">
31+
<int name="ChecksumField" type="uint8" />
32+
</checksum>
33+
</frame>
34+
</schema>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "cxxtest/TestSuite.h"
2+
3+
#include "test56/Message.h"
4+
#include "test56/frame/Frame.h"
5+
6+
#include "comms/process.h"
7+
8+
#include <cstdint>
9+
#include <type_traits>
10+
11+
class TestSuite : public CxxTest::TestSuite
12+
{
13+
public:
14+
void test1();
15+
16+
// struct Handler
17+
// {
18+
// template <typename TMsg>
19+
// void handle(TMsg& msg)
20+
// {
21+
// static_cast<void>(msg);
22+
// }
23+
// };
24+
25+
using Interface = test56::Message<
26+
comms::option::app::IdInfoInterface,
27+
comms::option::app::LengthInfoInterface,
28+
comms::option::app::ReadIterator<const std::uint8_t*>,
29+
comms::option::app::WriteIterator<std::uint8_t*>,
30+
comms::option::app::NameInterface
31+
>;
32+
using Frame = test56::frame::Frame<Interface>;
33+
34+
TEST56_ALIASES_FOR_ALL_MESSAGES_DEFAULT_OPTIONS(,,Interface);
35+
};
36+
37+
void TestSuite::test1()
38+
{
39+
const std::uint8_t Buf[] = {
40+
0x3d, 0x3d, // Prefix
41+
static_cast<std::uint8_t>(test56::MsgId_M2),
42+
'h', 'e', 'l', 'l', 'o',
43+
0x40, 0x40, // Suffix
44+
0x94 // Checksum
45+
};
46+
const std::size_t BufSize = std::extent<decltype(Buf)>::value;
47+
48+
Frame frame;
49+
Frame::MsgPtr msgPtr;
50+
51+
auto iter = comms::readIteratorFor<Interface>(Buf);
52+
auto es = frame.read(msgPtr, iter, BufSize);
53+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
54+
TS_ASSERT(msgPtr);
55+
TS_ASSERT_EQUALS(msgPtr->getId(), test56::MsgId_M2);
56+
57+
auto* msg2 = static_cast<const Msg2*>(msgPtr.get());
58+
TS_ASSERT_EQUALS(msg2->field_f1().value(), "hello");
59+
60+
std::vector<std::uint8_t> outputBuf;
61+
outputBuf.resize(frame.length(*msgPtr));
62+
63+
auto writeIter = comms::writeIteratorFor<Interface>(outputBuf.data());
64+
es = frame.write(*msgPtr, writeIter, outputBuf.size());
65+
TS_ASSERT_EQUALS(es, comms::ErrorStatus::Success);
66+
TS_ASSERT_EQUALS(outputBuf.size(), BufSize);
67+
TS_ASSERT(std::equal(outputBuf.begin(), outputBuf.end(), Buf));
68+
}
69+

lib/include/commsdsl/gen/GenLayer.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ class COMMSDSL_API GenLayer : public GenElem
7474
virtual bool genWriteImpl() const;
7575
virtual bool genForceCommsOrderImpl(GenLayersAccessList& layers, bool& success) const;
7676

77+
bool genAdjustSuffixLayersOrder(GenLayersAccessList& layers, bool& success) const;
78+
7779
private:
7880
std::unique_ptr<GenLayerImpl> m_impl;
7981
};

lib/src/gen/GenChecksumLayer.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ bool GenChecksumLayer::genForceCommsOrderImpl(GenLayersAccessList& layers, bool&
8181
return false;
8282
}
8383

84+
genGenerator().genLogger().genDebug("Layer \"" + genParseObj().parseName() + "\" is a suffix expected to be relocated");
8485
auto& fromStr = obj.parseFromLayer();
8586
if (fromStr.empty()) {
8687
[[maybe_unused]] static constexpr bool Should_not_happen = false;
@@ -105,19 +106,17 @@ bool GenChecksumLayer::genForceCommsOrderImpl(GenLayersAccessList& layers, bool&
105106
return false;
106107
}
107108

108-
auto iterTmp = iter;
109-
std::advance(iterTmp, 1U);
110-
if (iterTmp == fromIter) {
111-
// Already in place
112-
success = true;
113-
return false;
109+
auto dist = std::distance(iter, fromIter);
110+
if (dist < 0) {
111+
// Not relocated yet
112+
genGenerator().genLogger().genDebug("Relocating \"" + genParseObj().parseName() + "\" to precede \"" + (*fromIter)->genParseObj().parseName() + "\"");
113+
auto* thisPtr = *iter;
114+
layers.erase(iter);
115+
layers.insert(fromIter, thisPtr);
114116
}
115117

116-
auto thisPtr = std::move(*iter);
117-
layers.erase(iter);
118-
layers.insert(fromIter, std::move(thisPtr));
119-
success = true;
120-
return true;
118+
// Already in place
119+
return genAdjustSuffixLayersOrder(layers, success);
121120
}
122121

123122
GenChecksumLayer::ParseChecksumLayer GenChecksumLayer::genChecksumDslObj() const

lib/src/gen/GenLayer.cpp

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
#include "commsdsl/gen/strings.h"
2424
#include "commsdsl/gen/util.h"
2525

26-
#include <cassert>
2726
#include <algorithm>
27+
#include <cassert>
28+
#include <iterator>
2829

2930
namespace commsdsl
3031
{
@@ -342,6 +343,79 @@ bool GenLayer::genForceCommsOrderImpl(GenLayersAccessList& layers, bool& success
342343
return false;
343344
}
344345

346+
bool GenLayer::genAdjustSuffixLayersOrder(GenLayersAccessList& layers, bool& success) const
347+
{
348+
auto* frame = genParentFrame();
349+
assert(frame != nullptr);
350+
auto& origLayers = frame->genLayers();
351+
auto thisOrigIter =
352+
std::find_if(
353+
origLayers.begin(), origLayers.end(),
354+
[this](auto& lPtr)
355+
{
356+
return lPtr.get() == this;
357+
});
358+
359+
assert(thisOrigIter != origLayers.end());
360+
361+
auto origPayloadIter =
362+
std::find_if(
363+
origLayers.begin(), origLayers.end(),
364+
[](const auto& lPtr)
365+
{
366+
return lPtr->genParseObj().parseKind() == commsdsl::parse::ParseLayer::ParseKind::Payload;
367+
});
368+
369+
auto thisIter =
370+
std::find_if(
371+
layers.begin(), layers.end(),
372+
[this](const auto* l)
373+
{
374+
return l == this;
375+
});
376+
assert(thisIter != layers.end());
377+
378+
auto payloadIter =
379+
std::find_if(
380+
layers.begin(), layers.end(),
381+
[](const auto* l)
382+
{
383+
return l->genParseObj().parseKind() == commsdsl::parse::ParseLayer::ParseKind::Payload;
384+
});
385+
386+
for (auto iter = origPayloadIter + 1U; iter != thisOrigIter; ++iter) {
387+
auto* otherLayer = iter->get();
388+
auto otherIter =
389+
std::find_if(
390+
layers.begin(), layers.end(),
391+
[otherLayer](const auto* l)
392+
{
393+
return l == otherLayer;
394+
});
395+
assert(otherIter != layers.end());
396+
397+
auto payloadDist = std::distance(payloadIter, otherIter);
398+
if (0 < payloadDist) {
399+
// The other layer is not relocated yet
400+
continue;
401+
}
402+
403+
auto dist = std::distance(thisIter, otherIter);
404+
if (dist < 0) {
405+
// The wrapping order is incorrect
406+
auto* thisPtr = *thisIter;
407+
layers.erase(thisIter);
408+
layers.insert(otherIter, thisPtr);
409+
success = true;
410+
return true;
411+
}
412+
}
413+
414+
// All suffix layers are in correct order
415+
success = true;
416+
return false;
417+
}
418+
345419
} // namespace gen
346420

347421
} // namespace commsdsl

lib/src/gen/GenSyncLayer.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -180,19 +180,17 @@ bool GenSyncLayer::genForceCommsOrderImpl(GenLayersAccessList& layers, bool& suc
180180
return false;
181181
}
182182

183-
auto iterTmp = iter;
184-
std::advance(iterTmp, 1U);
185-
if (iterTmp == nextIter) {
186-
// Already in place
187-
success = true;
188-
return false;
183+
auto dist = std::distance(iter, nextIter);
184+
if (dist < 0) {
185+
// Not relocated yet
186+
genGenerator().genLogger().genDebug("Relocating \"" + genParseObj().parseName() + "\" to precede \"" + (*nextIter)->genParseObj().parseName() + "\"");
187+
auto* thisPtr = *iter;
188+
layers.erase(iter);
189+
layers.insert(nextIter, thisPtr);
189190
}
190191

191-
auto thisPtr = std::move(*iter);
192-
layers.erase(iter);
193-
layers.insert(nextIter, std::move(thisPtr));
194-
success = true;
195-
return true;
192+
// Already in place
193+
return genAdjustSuffixLayersOrder(layers, success);
196194
}
197195

198196
GenSyncLayer::ParseSyncLayer GenSyncLayer::genSyncLayerDslObj() const

lib/src/parse/ParseChecksumLayerImpl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ bool ParseChecksumLayerImpl::parseVerifyImpl(const ParseLayerImpl::ParseLayersLi
8787
"Layer \"" << parseFrom() << "\" must appear before the \"" << parseName() << "\".";
8888
return false;
8989
}
90+
91+
auto payloadIdx = parseFindLayerIndex(layers, ParseKind::Payload);
92+
if (!parseVerifySuffixLayersOrder(layers, payloadIdx, thisIdx, fromIdx)) {
93+
return false;
94+
}
9095
}
9196

9297
if (!parseUntil().empty()) {

lib/src/parse/ParseLayerImpl.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <cassert>
3232
#include <iterator>
3333
#include <limits>
34+
#include <map>
3435
#include <set>
3536

3637
namespace commsdsl
@@ -39,6 +40,23 @@ namespace commsdsl
3940
namespace parse
4041
{
4142

43+
namespace
44+
{
45+
46+
const std::string& parseRetrieveSyncFrom(const ParseLayerImpl& layer)
47+
{
48+
assert(layer.parseKind() == ParseLayerImpl::ParseKind::Sync);
49+
return static_cast<const ParseSyncLayerImpl&>(layer).parseFrom();
50+
}
51+
52+
const std::string& parseRetrieveChecksumFrom(const ParseLayerImpl& layer)
53+
{
54+
assert(layer.parseKind() == ParseLayerImpl::ParseKind::Checksum);
55+
return static_cast<const ParseChecksumLayerImpl&>(layer).parseFrom();
56+
}
57+
58+
} // namespace
59+
4260
ParseLayerImpl::ParsePtr ParseLayerImpl::parseCreate(
4361
const std::string& kind,
4462
::xmlNodePtr node,
@@ -247,6 +265,45 @@ bool ParseLayerImpl::parseVerifyBeforePayload(const ParseLayerImpl::ParseLayersL
247265
return true;
248266
}
249267

268+
bool ParseLayerImpl::parseVerifySuffixLayersOrder(const ParseLayersList& layers, std::size_t payloadIdx, std::size_t layerIdx, std::size_t fromIdx)
269+
{
270+
for (auto midIdx = payloadIdx + 1U; midIdx < layerIdx; ++midIdx) {
271+
auto& midLayerPtr = layers[midIdx];
272+
assert(midLayerPtr);
273+
274+
using FromRetrieveFunc = const std::string& (*)(const ParseLayerImpl& layer);
275+
static const std::map<ParseKind, FromRetrieveFunc> Map = {
276+
{ParseKind::Sync, &parseRetrieveSyncFrom},
277+
{ParseKind::Checksum, &parseRetrieveChecksumFrom},
278+
};
279+
280+
auto iter = Map.find(midLayerPtr->parseKind());
281+
if (iter == Map.end()) {
282+
continue;
283+
}
284+
285+
auto func = iter->second;
286+
auto& midFrom = func(*midLayerPtr);
287+
288+
if (midFrom.empty()) {
289+
continue;
290+
}
291+
292+
auto midFromIdx = parseFindLayerIndex(layers, midFrom);
293+
if (midFromIdx < fromIdx) {
294+
auto layerIter = Map.find(layers[layerIdx]->parseKind());
295+
assert(layerIter != Map.end());
296+
auto layerFunc = layerIter->second;
297+
298+
parseLogError() << ParseXmlWrap::parseLogPrefix(parseGetNode()) <<
299+
"Layer \"" << layerFunc(*layers[layerIdx]) << "\" specified by the \"" << common::parseFromStr() << "\" follows \"" << midFrom << "\" specified by the preceding layer.";
300+
return false;
301+
}
302+
}
303+
304+
return true;
305+
}
306+
250307
std::size_t ParseLayerImpl::parseFindThisLayerIndex(const ParseLayerImpl::ParseLayersList& layers) const
251308
{
252309
auto iter =

lib/src/parse/ParseLayerImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class ParseLayerImpl : public ParseObject
146146
void parseReportUnexpectedPropertyValue(const std::string& propName, const std::string& propValue);
147147
bool parseVerifySingleLayer(const ParseLayersList& layers, const std::string& kindStr);
148148
bool parseVerifyBeforePayload(const ParseLayersList& layers);
149+
bool parseVerifySuffixLayersOrder(const ParseLayersList& layers, std::size_t payloadIdx, std::size_t layerIdx, std::size_t fromIdx);
149150
std::size_t parseFindThisLayerIndex(const ParseLayersList& layers) const;
150151
std::size_t parseFindLayerIndex(const ParseLayersList& layers, ParseKind lKind);
151152
std::size_t parseFindLayerIndex(const ParseLayersList& layers, const std::string& name);

0 commit comments

Comments
 (0)