MPowell said:
I'm going through the Koeing book Accelerated C++ in an attempt to
understand Container classes. Of course I'm going through a paradigm
shift from C to C++.
So now I've got
struct Header
{
int source : 3;
int length : 4;
int count : 9
}
struct My_Struct
{
Header header;
// data
}
struct My_Other_Struct
{
Header header;
// data
}
// then later ... Rx_1553_Data
void Rx_1553_Data ( void )
{
unsigned char buffer [ 512 ];
// later
Read_1553_Data ( CHANNEL_FIVE, &buffer );
Parse_Rx_Message (&buffer);
// more stuff.
}
One way is this:
==============
interfaces - in your header file
==============
//
// declare all the different "types" of messages
class AlphaMessageType;
class BetaMessageType;
....
class GammaMessageType;
//
// define the base message interface
class BaseMessageType
{
public:
virtual ~BaseMessageType() {};
virtual bool ProcessMe( MessageProcessor * processor ) = 0;
virtual bool Deserialize( void * data ) = 0;
};
//
// All classes that need to "process" a message derive from
// this class and implement the Process() methods they care about.
//
class MessageProcessor
{
public:
bool Process( AlphaMessageType * message ) { return false };
bool Process( BetaMessageType * message ) { return false };
...
bool Process( GammaMessageType * message ) { return false };
};
//
// define the specific INTERFACES for each type of message
//
class AlphaMessageType : public BaseMessageType
{
... stuff particular to AlpaMessageType ...
};
==========================
Message Implementations
//
// Each message has an implementation
//
class AlphaMessageTypeImpl : public AlphaMessageType
{
virtual bool ProcessMe( MessageProcessor * processor )
{
return processor->Process( this );
}
AlphaSerializedDataStuff * stuff;
... must implement message specific deserialiser
... and serializer
... and copier
... and whatever else that is message specific
};
//
// register the message in a factory registry ...
//
REGISTER_IN_FACTORY( AlphaMessageTypeImpl, AlphaMessageKey );
etc for all the message types.
BaseMessageType * Parse_Rx_Message( void * buffer )
{
Header * hdr = reinterpet_cast<Header *>( buffer );
if ( ! CheckHeader( hdr ) )
{
return false;
}
BaseMessageType * msg =
MessageFactoryCreate( GetMessageType( hdr ) );
if ( msg == 0 )
{
return 0;
}
if ( msg->Deserialize( buffer ) == false )
{
delete msg;
return 0;
}
return msg;
}
=========================
If you get clever, you can use a template to create message
implementations. There's a few more steps than what I show here but
this should be enough. Still a number of issues need to be solved here,
- partial deserialization issues
- endian issues
- forward compatability
- error recovery
Now, to process the message you can derive from MessageProcessor and
implement the methods that work for you or you can simply "cast" using
somthing like this:
template <typename T> class MessageCast
: public virtual MessageProcessor
{
T m_message;
public:
MessageCast( BaseMessageType * message )
: m_message( 0 )
{
if ( message != 0 ) {
message->ProcessMe( this );
}
}
bool Process( T w_message )
{
m_message = w_message;
return true;
}
operator T ()
{
return m_message;
}
};
This may be used just like dynamic_cast
e.g.
AlphaMessageType * amsg =
MessageCast<AlphaMessageType *>( base_msg );
if ( amsg != 0 )
{
// base_msg is an Alpha message - do somthing
.....
Now Parse_Rx_Message will look at the appropriate header then memcopy
to the appropriate struct (either My_Stuct or My_Other_Struct) .
Trouble is I'd like to keep 'this' generic. In essense, use a
container class to handle all the memcopy etc. This 'generic'
container class will setup structs, compare structs etc. Does anyone
have an example that does this.
Wading through Koeing and would like to overhaul some 'test' code
which will hopefully help me understand the template/container aspect
of ++.
In the above design, templates enter the picture once you have
solidified the requirements. At this point, I would write some test
code that would exercise all the failure scenarios so that you can
create a more generic interface and hence do s better job designing a
class hierarchy for message implementations.