Skip to content

Commit

Permalink
Supporting "reuse" and "reuseCode" properties for <message>-s.
Browse files Browse the repository at this point in the history
  • Loading branch information
arobenko committed Dec 10, 2024
1 parent dfd619f commit a35230a
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/src/parse/FieldImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ bool FieldImpl::checkReuse()
return false;
}

m_state.m_copyCodeFrom.clear();
auto codeIter = m_props.find(codeProp);
if (codeIter == m_props.end()) {
break;
Expand Down
59 changes: 59 additions & 0 deletions lib/src/parse/MessageImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ bool MessageImpl::parse()
}

return
checkReuse() &&
updateName() &&
updateDisplayName() &&
updateDescription() &&
Expand Down Expand Up @@ -361,6 +362,8 @@ const XmlWrap::NamesList& MessageImpl::commonProps()
common::constructAsReadCondStr(),
common::constructAsValidCondStr(),
common::failOnInvalidStr(),
common::reuseStr(),
common::reuseCodeStr(),
};

return CommonNames;
Expand Down Expand Up @@ -401,6 +404,62 @@ XmlWrap::NamesList MessageImpl::allNames()
return names;
}

bool MessageImpl::checkReuse()
{
auto& propStr = common::reuseStr();
if (!validateSinglePropInstance(propStr)) {
return false;
}

auto iter = m_props.find(propStr);
if (iter == m_props.end()) {
return true;
}

if (!m_protocol.isMessageReuseSupported()) {
logWarning() << XmlWrap::logPrefix(getNode()) <<
"Property \"" << propStr << "\" is not supported for DSL version " << m_protocol.currSchema().dslVersion() << ", ignoring...";
return true;
}

auto& valueStr = iter->second;
auto* msg = m_protocol.findMessage(valueStr);
if (msg == nullptr) {
logError() << XmlWrap::logPrefix(getNode()) <<
"The message \"" << valueStr << "\" hasn't been recorded yet.";
return false;
}

assert(msg != this);
Base::reuseState(*msg);
m_state = msg->m_state;

do {
auto& codeProp = common::reuseCodeStr();
if (!validateSinglePropInstance(codeProp, false)) {
return false;
}

m_state.m_copyCodeFrom.clear();
auto codeIter = m_props.find(codeProp);
if (codeIter == m_props.end()) {
break;
}

bool copyCode = false;
if (!validateAndUpdateBoolPropValue(codeProp, copyCode)) {
return false;
}

if (!copyCode) {
break;
}

m_state.m_copyCodeFrom = valueStr;
} while (false);
return true;
}

bool MessageImpl::updateName()
{
bool mustHave = m_state.m_name.empty();
Expand Down
73 changes: 72 additions & 1 deletion lib/src/parse/MessageImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@

#pragma once

#include <cstdint>
#include <memory>
#include <map>
#include <string>
#include <cstdint>
#include <tuple>
#include <utility>

#include "commsdsl/parse/Message.h"

Expand Down Expand Up @@ -197,6 +199,74 @@ class MessageImpl final : public Object
OptCondImplPtr m_validCond;
bool m_customizable = false;
bool m_failOnInvalid = false;

ReusableState() = default;
ReusableState(ReusableState&&) = default;

auto basicForwardAsTuple()
{
return
std::forward_as_tuple(
m_name,
m_displayName,
m_description,
m_id = 0,
m_order,
m_validateMinLength,
// m_fields,
// m_aliases,
m_platforms,
m_sender,
m_readOverride,
m_writeOverride,
m_refreshOverride,
m_lengthOverride,
m_validOverride,
m_nameOverride,
m_copyCodeFrom,
// m_construct,
// m_readCond,
// m_validCond,
m_customizable,
m_failOnInvalid
);
}

auto basicForwardAsTuple() const
{
return const_cast<ReusableState*>(this)->basicForwardAsTuple();
}

ReusableState& operator=(const ReusableState& other)
{
basicForwardAsTuple() = other.basicForwardAsTuple();

m_fields.clear();
m_fields.reserve(other.m_fields.size());
for (auto& f : other.m_fields) {
m_fields.push_back(f->clone());
}

m_aliases.clear();
m_aliases.reserve(other.m_aliases.size());
for (auto& a : other.m_aliases) {
m_aliases.push_back(a->clone());
}

if (other.m_construct) {
m_construct = other.m_construct->clone();
}

if (other.m_readCond) {
m_readCond = other.m_readCond->clone();
}

if (other.m_validCond) {
m_validCond = other.m_validCond->clone();
}

return *this;
}
};

LogWrapper logError() const;
Expand All @@ -214,6 +284,7 @@ class MessageImpl final : public Object
bool validateAndUpdateOverrideTypePropValue(const std::string& propName, OverrideType& value);
bool validateAndUpdateBoolPropValue(const std::string& propName, bool& value, bool mustHave = false);
void reportUnexpectedPropertyValue(const std::string& propName, const std::string& propValue);
bool checkReuse();
bool updateName();
bool updateDescription();
bool updateDisplayName();
Expand Down
5 changes: 5 additions & 0 deletions lib/src/parse/ProtocolImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,11 @@ bool ProtocolImpl::isValidateMinLengthForFieldsSupported() const
return isFeatureSupported(7U);
}

bool ProtocolImpl::isMessageReuseSupported() const
{
return isFeatureSupported(7U);
}

void ProtocolImpl::cbXmlErrorFunc(void* userData, const xmlError* err)
{
reinterpret_cast<ProtocolImpl*>(userData)->handleXmlError(err);
Expand Down
1 change: 1 addition & 0 deletions lib/src/parse/ProtocolImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ class ProtocolImpl
bool isExistsCheckInConditionalsSupported() const;
bool isValidValueInStringAndDataSupported() const;
bool isValidateMinLengthForFieldsSupported() const;
bool isMessageReuseSupported() const;

void setMultipleSchemasEnabled(bool value)
{
Expand Down
43 changes: 43 additions & 0 deletions lib/test/message/Schema32.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema name="Schema32" endian="Big" dslVersion="7">
<description>
Testing
</description>
<fields>
<string name="Msg1Name" defaultValue="Message 1" />
<string name="Msg2Name" defaultValue="Message 2" />
<enum name="MsgId" type="uint8">
<validValue name="Msg1" val="0" displayName="^Msg1Name" />
<validValue name="Msg2" val="1" displayName="^Msg2Name" />
</enum>
</fields>

<interface name="Message">
<bitfield name="Flags">
<set name="M1" bitLength="2">
<bit name="B0" idx="0" />
<bit name="B1" idx="1" />
</set>
<int name="M2" type="uint8" bitLength="3" />
<int name="M3" type="uint8" bitLength="3" />
</bitfield>
</interface>

<message name="Msg1" id="MsgId.Msg1" displayName="^Msg1Name" failOnInvalid="true">
<fields>
<int name="F1" type="uint8" />
<int name="F2" type="uint8" />
</fields>
<validCond>
<and>
<validCond value="%Flags.M2 = 1" />
<validCond value="$F1 = $F2" />
</and>
</validCond>
</message>

<message name="Msg2" reuse="Msg1" reuseCode="true" id="MsgId.Msg2" displayName="^Msg2Name">
<int name="F3" type="uint8" />
</message>

</schema>
35 changes: 35 additions & 0 deletions lib/test/message/messageTest.th
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public:
void test29();
void test30();
void test31();
void test32();
};

void MessageTestSuite::setUp()
Expand Down Expand Up @@ -666,4 +667,38 @@ void MessageTestSuite::test31()
TS_ASSERT(msg1.isFailOnInvalid());
auto msg1ValidCond = msg1.validCond();
TS_ASSERT_EQUALS(msg1ValidCond.kind(), commsdsl::parse::OptCond::Kind::List);
}

void MessageTestSuite::test32()
{
auto protocol = prepareProtocol(SCHEMAS_DIR "/Schema32.xml");
TS_ASSERT(protocol);

auto namespaces = protocol->lastParsedSchema().namespaces();
TS_ASSERT_EQUALS(namespaces.size(), 1U);

auto& ns = namespaces.front();
TS_ASSERT(ns.name().empty());

auto messages = ns.messages();
{
TS_ASSERT_LESS_THAN_EQUALS(1U, messages.size());

auto& msg1 = messages[0];
TS_ASSERT(msg1.isFailOnInvalid());
TS_ASSERT_EQUALS(msg1.fields().size(), 2U);
auto msg1ValidCond = msg1.validCond();
TS_ASSERT_EQUALS(msg1ValidCond.kind(), commsdsl::parse::OptCond::Kind::List);
}

{
TS_ASSERT_LESS_THAN_EQUALS(2U, messages.size());

auto& msg2 = messages[1];
TS_ASSERT(msg2.isFailOnInvalid());
TS_ASSERT_EQUALS(msg2.fields().size(), 3U);
TS_ASSERT_EQUALS(msg2.copyCodeFrom(), "Msg1");
auto msg1ValidCond = msg2.validCond();
TS_ASSERT_EQUALS(msg1ValidCond.kind(), commsdsl::parse::OptCond::Kind::List);
}
}

0 comments on commit a35230a

Please sign in to comment.