COMMS
Template library intended to help with implementation of communication protocols.
|
#include "comms/Message.h"
Main interface class for all the messages.
Provides basic interface for all the messages.
TOptions | Variadic template parameter that contain any number of options to define functionality/behaviour of the message. The options may be comma separated as well as bundled into std::tuple. Supported options are:
|
Public Types | |
using | DispatchRetType = typename Handler::RetType |
Return type of the dispatch() member function. | |
using | Endian = typename BaseImpl::Endian |
Serialisation endian type. | |
using | Field = BaseImpl::Field |
Type of default base class for all the fields. | |
using | Handler = TypeProvidedWithOption |
Type of the message handler object. | |
using | InterfaceOptions = details::MessageInterfaceOptionsParser< TOptions... > |
All the options bundled into struct. | |
using | MsgIdParamType = typename BaseImpl::MsgIdParamType |
Type used for message ID passed as parameter or returned from function. | |
using | MsgIdType = typename BaseImpl::MsgIdType |
Type used for message ID. | |
using | ReadIterator = TypeProvidedWithOption |
Type of the iterator used for reading message contents from sequence of bytes stored somewhere. | |
using | TransportFields = FieldsProvidedWithOption |
std::tuple of extra fields from transport layers that may affect the way the message fields get serialized / deserialized. | |
using | VersionType = typename BaseImpl::VersionType |
Type used for version info. | |
using | WriteIterator = TypeProvidedWithOption |
Type of the iterator used for writing message contents into sequence of bytes stored somewhere. | |
Public Member Functions | |
~Message () noexcept=default | |
Destructor. | |
DispatchRetType | dispatch (Handler &handler) |
Dispatch message to the handler for processing. | |
MsgIdParamType | getId () const |
Retrieve ID of the message. | |
std::size_t | length () const |
Get number of bytes required to serialise this message. | |
const char * | name () const |
Get name of the message. | |
ErrorStatus | read (ReadIterator &iter, std::size_t size) |
Read message contents using provided iterator. | |
bool | refresh () |
Refresh to contents of the message. | |
TransportFields & | transportFields () |
Get access to extra transport fields. | |
const TransportFields & | transportFields () const |
Const version of transportFields. | |
bool | valid () const |
Check validity of message contents. | |
VersionType & | version () |
Access to version information. | |
const VersionType & | version () const |
Const access to version information. | |
ErrorStatus | write (WriteIterator &iter, std::size_t size) const |
Write message contents using provided iterator. | |
Static Public Member Functions | |
static constexpr bool | hasDispatch () |
Compile type inquiry whether message interface class defines dispatch() and dispatchImpl() member functions as well as Handler and DispatchRetType types. | |
static constexpr bool | hasEndian () |
Compile type inquiry whether message interface class defines Endian and Field types. | |
static constexpr bool | hasGetId () |
Compile type inquiry whether message interface class defines getId() and getIdImpl() member functions. | |
static constexpr bool | hasLength () |
Compile type inquiry whether message interface class defines length() and lengthImpl() member functions. | |
static constexpr bool | hasMsgIdType () |
Compile type inquiry whether message interface class defines MsgIdType and MsgIdParamType types. | |
static constexpr bool | hasName () |
Compile type inquiry whether message interface class defines name() and nameImpl() member functions. | |
static constexpr bool | hasRead () |
Compile type inquiry whether message interface class defines read() and readImpl() member functions as well as ReadIterator type. | |
static constexpr bool | hasRefresh () |
Compile type inquiry whether message interface class defines refresh() and refreshImpl() member functions. | |
static constexpr bool | hasTransportFields () |
Compile type inquiry whether message interface class defines transportFields() member functions as well as TransportFields type. | |
static constexpr bool | hasValid () |
Compile type inquiry whether message interface class defines valid() and validImpl() member functions. | |
static constexpr bool | hasVersionInTransportFields () |
Compile type inquiry whether there is version information inside transport fields. | |
static constexpr bool | hasWrite () |
Compile type inquiry whether message interface class defines write() and writeImpl() member functions as well as WriteIterator type. | |
static constexpr std::size_t | versionIdxInTransportFields () |
Compile type inquiry of version field index in transport field. | |
Protected Member Functions | |
virtual DispatchRetType | dispatchImpl (Handler &handler) |
Virtual function used to dispatch message to the handler object for processing. | |
virtual MsgIdParamType | getIdImpl () const =0 |
Pure virtual function used to retrieve ID of the message. | |
virtual std::size_t | lengthImpl () const |
Virtual function used to retrieve number of bytes required to serialise this message. | |
virtual const char * | nameImpl () const =0 |
Pure virtual function used to retrieve actual message name. | |
virtual comms::ErrorStatus | readImpl (ReadIterator &iter, std::size_t size) |
Virtual function used to implement read operation. | |
virtual bool | refreshImpl () |
Virtual function used to bring contents of the message into a consistent state. | |
virtual bool | validImpl () const |
Pure virtual function used to implement contents validity check. | |
virtual comms::ErrorStatus | writeImpl (WriteIterator &iter, std::size_t size) const |
Virtual function used to implement write operation. | |
Static Protected Member Functions | |
template<typename T , typename TIter > | |
static T | readData (TIter &iter) |
Read data from input area. | |
template<typename T , std::size_t TSize, typename TIter > | |
static T | readData (TIter &iter) |
Read partial data from input area. | |
template<typename T , typename TIter > | |
static void | writeData (T value, TIter &iter) |
Write data into the output area. | |
template<std::size_t TSize, typename T , typename TIter > | |
static void | writeData (T value, TIter &iter) |
Write partial data into the output area. | |
Related Symbols | |
(Note that these are not member symbols.) | |
#define | COMMS_MSG_TRANSPORT_FIELD_ALIAS(f_, ...) |
Generate convinience alias access member functions for extra member transport fields. | |
#define | COMMS_MSG_TRANSPORT_FIELD_ALIAS_ACCESS(f_, ...) COMMS_EXPAND(COMMS_DO_ALIAS(transportField_, f_, __VA_ARGS__)) |
Generate convinience alias access member functions for extra member transport fields. | |
#define | COMMS_MSG_TRANSPORT_FIELDS_ACCESS(...) |
Add convenience access enum and functions to extra transport fields. | |
#define | COMMS_MSG_TRANSPORT_FIELDS_NAMES(...) |
Provide names for extra transport fields. | |
using comms::Message< TOptions >::DispatchRetType = typename Handler::RetType |
Return type of the dispatch() member function.
Equal to Handler::RetType if such exists, void otherwise.
using comms::Message< TOptions >::Endian = typename BaseImpl::Endian |
Serialisation endian type.
The type exists only if comms::option::def::BigEndian or comms::option::def::LittleEndian options were used to specify it.
using comms::Message< TOptions >::Field = BaseImpl::Field |
Type of default base class for all the fields.
Requires definition of the Endian type, i.e. the type exist only if comms::option::def::BigEndian or comms::option::def::LittleEndian options were used.
using comms::Message< TOptions >::Handler = TypeProvidedWithOption |
Type of the message handler object.
The type exists only if comms::option::app::Handler option was provided to comms::Message to specify one.
using comms::Message< TOptions >::InterfaceOptions = details::MessageInterfaceOptionsParser<TOptions...> |
All the options bundled into struct.
For internal use only.
using comms::Message< TOptions >::MsgIdParamType = typename BaseImpl::MsgIdParamType |
Type used for message ID passed as parameter or returned from function.
It is equal to MsgIdType for numeric types and becomes "const-reference-to" MsgIdType for more complex types. The type exists only if MsgIdType exists, i.e. the comms::option::def::MsgIdType option was used.
using comms::Message< TOptions >::MsgIdType = typename BaseImpl::MsgIdType |
Type used for message ID.
The type exists only if comms::option::def::MsgIdType option was provided to comms::Message to specify it.
using comms::Message< TOptions >::ReadIterator = TypeProvidedWithOption |
Type of the iterator used for reading message contents from sequence of bytes stored somewhere.
The type exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify one.
using comms::Message< TOptions >::TransportFields = FieldsProvidedWithOption |
std::tuple of extra fields from transport layers that may affect the way the message fields get serialized / deserialized.
The type exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them.
using comms::Message< TOptions >::VersionType = typename BaseImpl::VersionType |
Type used for version info.
The type exists only if comms::option::def::VersionInExtraTransportFields option has been provided.
using comms::Message< TOptions >::WriteIterator = TypeProvidedWithOption |
Type of the iterator used for writing message contents into sequence of bytes stored somewhere.
The type exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify one.
|
defaultnoexcept |
Destructor.
Becomes virtual if the message interface is defined to expose any polymorphic behavior, i.e. if there is at least one virtual function. It is possible to explicitly suppress virtual declaration by using comms::option::app::NoVirtualDestructor option.
DispatchRetType comms::Message< TOptions >::dispatch | ( | Handler & | handler | ) |
Dispatch message to the handler for processing.
The function exists only if comms::option::app::Handler option was provided to comms::Message to specify type of the handler. The function invokes virtual dispatchImpl() function.
handler | Handler object to dispatch message to. |
|
protectedvirtual |
Virtual function used to dispatch message to the handler object for processing.
Called by dispatch(), must be implemented in the derived class. The function exists only if comms::option::app::Handler option was provided to comms::Message to specify type of the handler. If not overridden unconditionally fails on assert in DEBUG build and does nothing in RELEASE.
handler | Handler object to dispatch message to. |
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
MsgIdParamType comms::Message< TOptions >::getId | ( | ) | const |
Retrieve ID of the message.
Invokes pure virtual getIdImpl(). This function exists only if comms::option::def::MsgIdType option was used to specify type of the ID value and comms::option::app::IdInfoInterface option are used.
|
protectedpure virtual |
Pure virtual function used to retrieve ID of the message.
Called by getId(), must be implemented in the derived class. This function exists only if comms::option::def::MsgIdType option was used to specify type of the ID value as well as comms::option::app::IdInfoInterface.
Implemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
std::size_t comms::Message< TOptions >::length | ( | ) | const |
Get number of bytes required to serialise this message.
The function exists only if comms::option::app::LengthInfoInterface option was provided to comms::Message. The function invokes virtual lengthImpl() function.
|
protectedvirtual |
Virtual function used to retrieve number of bytes required to serialise this message.
Called by length(), must be implemented in the derived class. The function exists only if comms::option::app::LengthInfoInterface option was provided to comms::Message.
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
const char * comms::Message< TOptions >::name | ( | ) | const |
Get name of the message.
The function exists only if comms::option::app::NameInterface option was provided to comms::Message. The function invokes virtual nameImpl() function.
|
protectedpure virtual |
Pure virtual function used to retrieve actual message name.
Called by name(), must be implemented in the derived class. The function exists only if comms::option::app::NameInterface option was provided to comms::Message.
Implemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
ErrorStatus comms::Message< TOptions >::read | ( | ReadIterator & | iter, |
std::size_t | size | ||
) |
Read message contents using provided iterator.
The function exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify type of the ReadIterator. The contents of the message are updated with bytes being read. The buffer is external and maintained by the caller. The provided iterator is advanced. The function invokes virtual readImpl() function.
[in,out] | iter | Iterator used for reading the data. |
[in] | size | Maximum number of bytes that can be read. |
|
staticprotected |
Read data from input area.
Use this function to read data from the input area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.
T | Return type |
TIter | Type of input iterator |
[in,out] | iter | Input iterator. |
|
staticprotected |
Read partial data from input area.
Use this function to read partial data from the input area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.
T | Return type |
TSize | number of bytes to read |
TIter | Type of input iterator |
[in,out] | iter | Input iterator. |
|
protectedvirtual |
Virtual function used to implement read operation.
Called by read(), expected be implemented in the derived class. The function exists only if comms::option::app::ReadIterator option was provided to comms::Message to specify type of the ReadIterator.
[in,out] | iter | Iterator used for reading the data. |
[in] | size | Maximum number of bytes that can be read. |
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
bool comms::Message< TOptions >::refresh | ( | ) |
Refresh to contents of the message.
Many protocols define their messages in a way that the content of some fields may depend on the value of the other field(s). For example, providing in one field the information about number of elements in the list that will follow later. Another example is having bits in a bitmask field specifying whether other optional fields exist. In this case, directly modifying value of some fields may leave a message contents in an inconsistent state. Having refresh() member function allows the developer to bring the message into a consistent state prior to sending it over I/O link .
The function exists only if comms::option::app::RefreshInterface option was provided to comms::Message. The function invokes virtual refreshImpl() function.
|
protectedvirtual |
Virtual function used to bring contents of the message into a consistent state.
Called by refresh(), can be overridden in the derived class. If not overridden, does nothing and returns false indicating that contents of the message haven't been changed. The function exists only if comms::option::app::RefreshInterface option was provided to comms::Message.
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
TransportFields & comms::Message< TOptions >::transportFields | ( | ) |
Get access to extra transport fields.
The function exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them. Some protocols may use additional values in transport information, such as message version for example. Such values may influence the way message data is being serialized / deserialized. The provided extra transport fields are NOT serialised as part of message payload. Their values are expected to be set by transport layer(s) when such information is read. The transport layers are also responsible to take the updated information from the relevant field and write it when message contents being written.
const TransportFields & comms::Message< TOptions >::transportFields | ( | ) | const |
Const version of transportFields.
The function exists only if comms::option::def::ExtraTransportFields option has been provided to comms::Message class to specify them.
bool comms::Message< TOptions >::valid | ( | ) | const |
Check validity of message contents.
The function exists only if comms::option::app::ValidCheckInterface option was provided to comms::Message. The function invokes virtual validImpl() function.
|
protectedvirtual |
Pure virtual function used to implement contents validity check.
Called by valid(), must be implemented in the derived class. The function exists only if comms::option::app::ValidCheckInterface option was provided to comms::Message.
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
VersionType & comms::Message< TOptions >::version | ( | ) |
Access to version information.
The function exists only if comms::option::def::VersionInExtraTransportFields option has been provided.
const VersionType & comms::Message< TOptions >::version | ( | ) | const |
Const access to version information.
The function exists only if comms::option::def::VersionInExtraTransportFields option has been provided.
|
staticconstexpr |
Compile type inquiry of version field index in transport field.
If comms::option::def::VersionInExtraTransportFields option hasn't been used, the std::numeric_limits<std::size_t>::max() is returned.
ErrorStatus comms::Message< TOptions >::write | ( | WriteIterator & | iter, |
std::size_t | size | ||
) | const |
Write message contents using provided iterator.
The function exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify type of the WriteIterator. The contents of the message are serialised into buffer. The buffer is external and is maintained by the caller. The provided iterator is advanced. The function invokes virtual writeImpl() function.
[in,out] | iter | Iterator used for writing the data. |
[in] | size | Maximum number of bytes that can be written. |
|
staticprotected |
Write data into the output area.
Use this function to write data to the output area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.
T | Type of the value to write. Must be integral. |
Type | of output iterator |
[in] | value | Integral type value to be written. |
[in,out] | iter | Output iterator. |
|
staticprotected |
Write partial data into the output area.
Use this function to write partial data to the output area using provided iterator. This function requires knowledge about serialisation endian. It exists only if endian type was specified using comms::option::def::BigEndian or comms::option::def::LittleEndian options to the class.
TSize | Length of the value in bytes known in compile time. |
T | Type of the value to write. Must be integral. |
TIter | Type of output iterator |
[in] | value | Integral type value to be written. |
[in,out] | iter | Output iterator. |
|
protectedvirtual |
Virtual function used to implement write operation.
Called by write(), expected be implemented in the derived class. The function exists only if comms::option::app::WriteIterator option was provided to comms::Message to specify type of the WriteIterator.
[in,out] | iter | Iterator used for writing the data. |
[in] | size | Maximum number of bytes that can be written. |
Reimplemented in comms::MessageBase< TMessage, TOptions >, and comms::MessageBase< TMessage, comms::option::def::FieldsImpl< GenericMessageFields< TMessage::Field, comms::option::app::EmptyOption > >, comms::option::def::MsgType< GenericMessage< TMessage, comms::option::app::EmptyOption, comms::option::app::EmptyOption > >, comms::option::def::HasDoGetId, comms::option::def::HasName, comms::option::app::EmptyOption >.
|
related |
Generate convinience alias access member functions for extra member transport fields.
The COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro generates alias type as well as convenience access member functions for extra transport fields. Sometimes the fields may get renamed or moved to be a member of other fields, like comms::field::Bundle or comms::field::Bitfield. In such case the compilation of the existing client code (that already uses published protocol definition) may fail. To avoid such scenarios and make the transition to newer versions of the protocol easier, the COMMS_MSG_TRANSPORT_FIELD_ALIAS() macro can be used to create alias to other fields. For example, let's assume that some common interface class was defined: like this.
In the future versions of the protocol "name3" was renamed to "newName3". To keep the existing code (that uses "name3" name) compiling it is possible to create an alias access function(s) with:
The usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() in the code above is equivalent to having the following type and functions defined:
Another example would be a replacing a comms::field::IntValue with comms::field::Bitfield in the future version of the protocol. It can happen when the developer decides to split the used storage into multiple values (because the range of the used/valid values allows so). In order to keep the old client code compiling, the access to the replaced field needs to be an alias to the first member of the comms::field::Bitfield. In this case the usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() will look like this:
The usage of COMMS_MSG_TRANSPORT_FIELD_ALIAS() in the code above is equivalent to having the following functions defined:
[in] | f_ | Alias field name. |
[in] | ... | List of fields' names. |
|
related |
Generate convinience alias access member functions for extra member transport fields.
Similar to COMMS_MSG_TRANSPORT_FIELD_ALIAS() but requires usage of COMMS_MSG_TRANSPORT_FIELDS_ACCESS() instead of COMMS_MSG_TRANSPORT_FIELDS_NAMES() and does NOT create alias to the field type, only access functions.
[in] | f_ | Alias field name. |
[in] | ... | List of fields' names. |
|
related |
Add convenience access enum and functions to extra transport fields.
Very similar to COMMS_MSG_TRANSPORT_FIELDS_NAMES(), but does NOT require definition of Base inner member type (for some compilers) and does NOT define inner TransportField_* types for used fields.
[in] | ... | List of fields' names. |
|
related |
Provide names for extra transport fields.
The comms::Message class provides access to its extra transport fields via comms::MessageBase::transportFields() member function(s). The fields are bundled into std::tuple and can be accessed using indices with std::get. For convenience, the fields should be named. The COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro does exactly that.
As an example, let's assume that custom message uses 3 fields of any types:
The usage of the COMMS_MSG_TRANSPORT_FIELDS_NAMES() macro with the list of the extra transport field's names is equivalent to having the following definitions inside the message class
NOTE, that provided names name1, name2, and name3 have found their way to the following definitions:
As the result, the fields can be accessed using TransportFieldIdx enum
or using accessor functions:
[in] | ... | List of fields' names. |