123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- /* -*- C++ -*- */
- /****************************************************************************
- ** Copyright (c) 2001-2014
- **
- ** This file is part of the QuickFIX FIX Engine
- **
- ** This file may be distributed under the terms of the quickfixengine.org
- ** license as defined by quickfixengine.org and appearing in the file
- ** LICENSE included in the packaging of this file.
- **
- ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** See http://www.quickfixengine.org/LICENSE for licensing information.
- **
- ** Contact ask@quickfixengine.org if any conditions of this licensing are
- ** not clear to you.
- **
- ****************************************************************************/
- #ifndef FIX_MESSAGE
- #define FIX_MESSAGE
- #ifdef _MSC_VER
- #pragma warning( disable: 4786 )
- #endif
- #include "FieldMap.h"
- #include "Fields.h"
- #include "Group.h"
- #include "SessionID.h"
- #include "DataDictionary.h"
- #include "Values.h"
- #include <vector>
- #include <memory>
- namespace FIX
- {
- static int const headerOrder[] =
- {
- FIELD::BeginString,
- FIELD::BodyLength,
- FIELD::MsgType
- };
- class Header : public FieldMap
- {
- public:
- Header() : FieldMap(message_order( message_order::header ) )
- {}
- };
- class Trailer : public FieldMap
- {
- public:
- Trailer() : FieldMap(message_order( message_order::trailer ) )
- {}
- };
- /**
- * Base class for all %FIX messages.
- *
- * A message consists of three field maps. One for the header, the body,
- * and the trailer.
- */
- class Message : public FieldMap
- {
- friend class DataDictionary;
- friend class Session;
- enum field_type { header, body, trailer };
- public:
- Message();
- /// Construct a message from a string
- Message( const std::string& string, bool validate = true )
- throw( InvalidMessage );
- /// Construct a message from a string using a data dictionary
- Message( const std::string& string, const FIX::DataDictionary& dataDictionary,
- bool validate = true )
- throw( InvalidMessage );
- /// Construct a message from a string using a session and application data dictionary
- Message( const std::string& string, const FIX::DataDictionary& sessionDataDictionary,
- const FIX::DataDictionary& applicationDataDictionary, bool validate = true )
- throw( InvalidMessage );
- Message( const Message& copy )
- : FieldMap( copy )
- {
- m_header = copy.m_header;
- m_trailer = copy.m_trailer;
- m_validStructure = copy.m_validStructure;
- m_field = copy.m_field;
- }
- /// Set global data dictionary for encoding messages into XML
- static bool InitializeXML( const std::string& string );
- void addGroup( const FIX::Group& group )
- { FieldMap::addGroup( group.field(), group ); }
- void replaceGroup( unsigned num, const FIX::Group& group )
- { FieldMap::replaceGroup( num, group.field(), group ); }
- Group& getGroup( unsigned num, FIX::Group& group ) const throw( FieldNotFound )
- { group.clear();
- return static_cast < Group& >
- ( FieldMap::getGroup( num, group.field(), group ) );
- }
- void removeGroup( unsigned num, const FIX::Group& group )
- { FieldMap::removeGroup( num, group.field() ); }
- void removeGroup( const FIX::Group& group )
- { FieldMap::removeGroup( group.field() ); }
- bool hasGroup( const FIX::Group& group ) const
- { return FieldMap::hasGroup( group.field() ); }
- bool hasGroup( unsigned num, const FIX::Group& group ) const
- { return FieldMap::hasGroup( num, group.field() ); }
- protected:
- // Constructor for derived classes
- Message( const BeginString& beginString, const MsgType& msgType )
- : m_validStructure( true )
- {
- m_header.setField( beginString );
- m_header.setField( msgType );
- }
- public:
- /// Get a string representation of the message
- std::string toString( int beginStringField = FIELD::BeginString,
- int bodyLengthField = FIELD::BodyLength,
- int checkSumField = FIELD::CheckSum ) const;
- /// Get a string representation without making a copy
- std::string& toString( std::string&,
- int beginStringField = FIELD::BeginString,
- int bodyLengthField = FIELD::BodyLength,
- int checkSumField = FIELD::CheckSum ) const;
- /// Get a XML representation of the message
- std::string toXML() const;
- /// Get a XML representation without making a copy
- std::string& toXML( std::string& ) const;
- /**
- * Add header informations depending on a source message.
- * This can be used to add routing informations like OnBehalfOfCompID
- * and DeliverToCompID to a message.
- */
- void reverseRoute( const Header& );
- /**
- * Set a message based on a string representation
- * This will fill in the fields on the message by parsing out the string
- * that is passed in. It will return true on success and false
- * on failure.
- */
- void setString( const std::string& string )
- throw( InvalidMessage )
- { setString(string, true); }
- void setString( const std::string& string, bool validate )
- throw( InvalidMessage )
- { setString(string, validate, 0); }
- void setString( const std::string& string,
- bool validate,
- const FIX::DataDictionary* pDataDictionary )
- throw( InvalidMessage )
- { setString(string, validate, pDataDictionary, pDataDictionary); }
- void setString( const std::string& string,
- bool validate,
- const FIX::DataDictionary* pSessionDataDictionary,
- const FIX::DataDictionary* pApplicationDataDictionary )
- throw( InvalidMessage );
- void setGroup( const std::string& msg, const FieldBase& field,
- const std::string& string, std::string::size_type& pos,
- FieldMap& map, const DataDictionary& dataDictionary );
- /**
- * Set a messages header from a string
- * This is an optimization that can be used to get useful information
- * from the header of a FIX string without parsing the whole thing.
- */
- bool setStringHeader( const std::string& string );
- /// Getter for the message header
- const Header& getHeader() const { return m_header; }
- /// Mutable getter for the message header
- Header& getHeader() { return m_header; }
- /// Getter for the message trailer
- const Trailer& getTrailer() const { return m_trailer; }
- /// Mutable getter for the message trailer
- Trailer& getTrailer() { return m_trailer; }
- bool hasValidStructure(int& field) const
- { field = m_field;
- return m_validStructure;
- }
- int bodyLength( int beginStringField = FIELD::BeginString,
- int bodyLengthField = FIELD::BodyLength,
- int checkSumField = FIELD::CheckSum ) const
- { return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)
- + calculateLength(beginStringField, bodyLengthField, checkSumField)
- + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);
- }
- int checkSum( int checkSumField = FIELD::CheckSum ) const
- { return ( m_header.calculateTotal(checkSumField)
- + calculateTotal(checkSumField)
- + m_trailer.calculateTotal(checkSumField) ) % 256;
- }
- bool isAdmin() const
- {
- if( m_header.isSetField(FIELD::MsgType) )
- {
- const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
- return isAdminMsgType( msgType );
- }
- return false;
- }
- bool isApp() const
- {
- if( m_header.isSetField(FIELD::MsgType) )
- {
- const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
- return !isAdminMsgType( msgType );
- }
- return false;
- }
- bool isEmpty()
- { return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }
- void clear()
- {
- m_field = 0;
- m_header.clear();
- FieldMap::clear();
- m_trailer.clear();
- }
- static bool isAdminMsgType( const MsgType& msgType )
- { if ( msgType.getValue().length() != 1 ) return false;
- return strchr
- ( "0A12345",
- msgType.getValue().c_str() [ 0 ] ) != 0;
- }
- static ApplVerID toApplVerID(const BeginString& value)
- {
- if( value == BeginString_FIX40 )
- return ApplVerID(ApplVerID_FIX40);
- if( value == BeginString_FIX41 )
- return ApplVerID(ApplVerID_FIX41);
- if( value == BeginString_FIX42 )
- return ApplVerID(ApplVerID_FIX42);
- if( value == BeginString_FIX43 )
- return ApplVerID(ApplVerID_FIX43);
- if( value == BeginString_FIX44 )
- return ApplVerID(ApplVerID_FIX44);
- if( value == BeginString_FIX50 )
- return ApplVerID(ApplVerID_FIX50);
- if( value == "FIX.5.0SP1" )
- return ApplVerID(ApplVerID_FIX50SP1);
- if( value == "FIX.5.0SP2" )
- return ApplVerID(ApplVerID_FIX50SP2);
- return ApplVerID(ApplVerID(value));
- }
- static BeginString toBeginString( const ApplVerID& applVerID )
- {
- if( applVerID == ApplVerID_FIX40 )
- return BeginString(BeginString_FIX40);
- else if( applVerID == ApplVerID_FIX41 )
- return BeginString(BeginString_FIX41);
- else if( applVerID == ApplVerID_FIX42 )
- return BeginString(BeginString_FIX42);
- else if( applVerID == ApplVerID_FIX43 )
- return BeginString(BeginString_FIX43);
- else if( applVerID == ApplVerID_FIX44 )
- return BeginString(BeginString_FIX44);
- else if( applVerID == ApplVerID_FIX50 )
- return BeginString(BeginString_FIX50);
- else if( applVerID == ApplVerID_FIX50SP1 )
- return BeginString(BeginString_FIX50);
- else if( applVerID == ApplVerID_FIX50SP2 )
- return BeginString(BeginString_FIX50);
- else
- return BeginString("");
- }
- static bool isHeaderField( int field );
- static bool isHeaderField( const FieldBase& field,
- const DataDictionary* pD = 0 );
- static bool isTrailerField( int field );
- static bool isTrailerField( const FieldBase& field,
- const DataDictionary* pD = 0 );
- /// Returns the session ID of the intended recipient
- SessionID getSessionID( const std::string& qualifier = "" ) const
- throw( FieldNotFound );
- /// Sets the session ID of the intended recipient
- void setSessionID( const SessionID& sessionID );
- private:
- FieldBase extractField(
- const std::string& string, std::string::size_type& pos,
- const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
- const Group* pGroup = 0);
- static bool IsDataField(
- int field,
- const DataDictionary* pSessionDD,
- const DataDictionary* pAppDD )
- {
- if( (pSessionDD && pSessionDD->isDataField( field )) ||
- (pAppDD && pAppDD != pSessionDD && pAppDD->isDataField( field )) )
- {
- return true;
- }
- return false;
- }
- void validate();
- std::string toXMLFields(const FieldMap& fields, int space) const;
- protected:
- mutable Header m_header;
- mutable Trailer m_trailer;
- bool m_validStructure;
- int m_field;
- static std::auto_ptr<DataDictionary> s_dataDictionary;
- };
- /*! @} */
- inline std::ostream& operator <<
- ( std::ostream& stream, const Message& message )
- {
- std::string str;
- stream << message.toString( str );
- return stream;
- }
- /// Parse the type of a message from a string.
- inline MsgType identifyType( const std::string& message )
- throw( MessageParseError )
- {
- std::string::size_type pos = message.find( "\001" "35=" );
- if ( pos == std::string::npos ) throw MessageParseError();
- std::string::size_type startValue = pos + 4;
- std::string::size_type soh = message.find_first_of( '\001', startValue );
- if ( soh == std::string::npos ) throw MessageParseError();
- std::string value = message.substr( startValue, soh - startValue );
- return MsgType( value );
- }
- }
- #endif //FIX_MESSAGE
|