Container Class

Discussion in 'C++' started by MPowell, Sep 4, 2003.

  1. MPowell

    MPowell Guest

    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.
    }

    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 ++.

    Thanks in advance
    MPowell, Sep 4, 2003
    #1
    1. Advertising

  2. "MPowell" <> wrote...
    > 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.
    > }
    >
    > 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.


    Why not let each class handle its own copying/creation from bytes?

    > This 'generic'
    > container class will setup structs, compare structs etc. Does anyone
    > have an example that does this.


    Find and read about serialisation. It's not as simple an issue
    to be described in a reply to a newsgroup posting.

    In general, there should be some kind of distinctive marking in
    the memory that would make it one object and not any other. If
    you find that mark, then a serialiser object should be used to
    create a certain structure from the stream/bunch of bytes. The
    serialisers usually are registered with the stream reader and
    associated with those marks (or you could query all registered
    serialisers to know which one will be responsible)...

    > Wading through Koeing and would like to overhaul some 'test' code
    > which will hopefully help me understand the template/container aspect
    > of ++.


    I don't think you're in that area "of ++". I may be mistaken,
    of course.

    Victor
    Victor Bazarov, Sep 4, 2003
    #2
    1. Advertising

  3. MPowell wrote:
    > 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.
    Gianni Mariani, Sep 4, 2003
    #3
  4. MPowell

    Agent Mulder Guest

    <MPowell>
    I'm going through the Koeing book Accelerated C++ in an attempt to
    understand Container classes.
    </MPowell>

    What part of Accelerated C++ are you in?
    Agent Mulder, Sep 4, 2003
    #4
  5. MPowell

    red floyd Guest

    MPowell wrote:
    > [redacted]


    Totally OT, but what the hey. You have my sympathy. Actually, anybody who writes MIL-STD-1553 drivers
    has my sympathy (since I've been there, done that, and got the T-Shirt).

    red floyd
    red floyd, Sep 4, 2003
    #5
  6. MPowell

    MPowell Guest

    Gianni Mariani <> wrote in message news:<bj81c5$>...
    > MPowell wrote:
    > > 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
    >
    > };


    What exactly is a 'copier'? Book didnt seem to highlight that.
    Truly appreaciate the help. I suspect "Serialization" is the way to
    go. Would it be too much to ask for some assistance on say ONE
    complete class that highlights serialization from top to bottom, more
    specifically i'm trying to garner a feel for what the above means?

    >
    > //
    > // 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
    >



    Here again I'd really like to garner a feel for full understanding on
    some of this.


    > 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;
    > }
    >
    > };
    >

    Does teh Process (below) function above do a memcopy of sorts, or is
    that resident in the implementation of the specific class, derived off
    the base (MessageProcessor) class

    I'm off to read up on Serializing.


    > 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.


    Thanks a lot.... Good start.
    MPowell, Sep 4, 2003
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Vivi Orunitia
    Replies:
    11
    Views:
    4,470
    Martijn Lievaart
    Feb 4, 2004
  2. Maitre Bart
    Replies:
    2
    Views:
    520
    Maitre Bart
    Feb 11, 2004
  3. Steven T. Hatton
    Replies:
    4
    Views:
    3,895
    Rob Williscroft
    Dec 5, 2004
  4. Replies:
    4
    Views:
    797
    Daniel T.
    Feb 16, 2006
  5. wolverine
    Replies:
    2
    Views:
    449
    Marcus Kwok
    Jul 24, 2006
Loading...

Share This Page