Index  Source Files  Annotated Class List  Alphabetical Class List  Class Hierarchy  Graphical Class Hierarchy   
 

/home/orenmnero/autobuild/quickfix/src/C++/Message.h

Go to the documentation of this file.
00001 /* -*- C++ -*- */
00002 
00003 /****************************************************************************
00004 ** Copyright (c) quickfixengine.org  All rights reserved.
00005 **
00006 ** This file is part of the QuickFIX FIX Engine
00007 **
00008 ** This file may be distributed under the terms of the quickfixengine.org
00009 ** license as defined by quickfixengine.org and appearing in the file
00010 ** LICENSE included in the packaging of this file.
00011 **
00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00014 **
00015 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00016 **
00017 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00018 ** not clear to you.
00019 **
00020 ****************************************************************************/
00021 
00022 #ifndef FIX_MESSAGE
00023 #define FIX_MESSAGE
00024 
00025 #ifdef _MSC_VER
00026 #pragma warning( disable: 4786 )
00027 #endif
00028 
00029 #include "FieldMap.h"
00030 #include "Fields.h"
00031 #include "Group.h"
00032 #include "SessionID.h"
00033 #include "DataDictionary.h"
00034 #include "CallStack.h"
00035 #include <vector>
00036 #include <memory>
00037 
00038 namespace FIX
00039 {
00040 typedef FieldMap Header;
00041 typedef FieldMap Trailer;
00042 
00043 static FIELD::Field const headerOrder[] =
00044   {
00045     FIELD::BeginString,
00046     FIELD::BodyLength,
00047     FIELD::MsgType
00048   };
00049 
00056 class Message : public FieldMap
00057 {
00058   friend class DataDictionary;
00059   friend class Session;
00060 
00061   enum field_type { header, body, trailer };
00062 
00063 public:
00064   Message();
00065 
00067   Message( const std::string& string, bool validate = true )
00068   throw( InvalidMessage );
00069 
00071   Message( const std::string& string, const DataDictionary& dataDictionary,
00072            bool validate = true )
00073   throw( InvalidMessage );
00074 
00075   Message( const Message& copy )
00076   : FieldMap( copy ),
00077     m_header( message_order( message_order::header ) ),
00078     m_trailer( message_order( message_order::trailer ) )
00079   {
00080     m_header = copy.m_header;
00081     m_trailer = copy.m_trailer;
00082     m_validStructure = copy.m_validStructure;
00083     m_field = copy.m_field;
00084   }
00085 
00087   static bool InitializeXML( const std::string& string );
00088 
00089   void addGroup( FIX::Group& group )
00090   { FieldMap::addGroup( group.field(), group ); }
00091 
00092   void replaceGroup( unsigned num, FIX::Group& group )
00093   { FieldMap::replaceGroup( num, group.field(), group ); }
00094 
00095   Group& getGroup( unsigned num, FIX::Group& group ) const throw( FieldNotFound )
00096   { group.clear();
00097     return static_cast < Group& >
00098       ( FieldMap::getGroup( num, group.field(), group ) );
00099   }
00100 
00101   void removeGroup( unsigned num, FIX::Group& group )
00102   { FieldMap::removeGroup( num, group.field() ); }
00103   void removeGroup( FIX::Group& group )
00104   { FieldMap::removeGroup( group.field() ); }
00105 
00106   bool hasGroup( const FIX::Group& group )
00107   { return FieldMap::hasGroup( group.field() ); }
00108   bool hasGroup( unsigned num, FIX::Group& group )
00109   { return FieldMap::hasGroup( num, group.field() ); }
00110 
00111 protected:
00112   // Constructor for derived classes
00113   Message( const BeginString& beginString, const MsgType& msgType )
00114   : m_header( message_order( message_order::header ) ),
00115   m_trailer( message_order( message_order::trailer ) ),
00116   m_validStructure( true )
00117   {
00118     m_header.setField( beginString );
00119     m_header.setField( msgType );
00120   }
00121 
00122 public:
00124   std::string toString( int beginStringField = FIELD::BeginString,
00125                         int bodyLengthField = FIELD::BodyLength,
00126                         int checkSumField = FIELD::CheckSum ) const;
00128   std::string& toString( std::string&,
00129                          int beginStringField = FIELD::BeginString,
00130                          int bodyLengthField = FIELD::BodyLength, 
00131                          int checkSumField = FIELD::CheckSum ) const;
00133   std::string toXML() const;
00135   std::string& toXML( std::string& ) const;
00136 
00142   void reverseRoute( const Header& );
00143 
00150   void setString( const std::string& string,
00151                   bool validate = true,
00152                   const DataDictionary* pDataDictionary = 0 )
00153   throw( InvalidMessage );
00154 
00155   void setGroup( const std::string& msg, const FieldBase& field,
00156                  const std::string& string, std::string::size_type& pos,
00157                  FieldMap& map, const DataDictionary& dataDictionary );
00158 
00164   bool setStringHeader( const std::string& string );
00165 
00167   const Header& getHeader() const { return m_header; }
00169   Header& getHeader() { return m_header; }
00171   const Header& getTrailer() const { return m_trailer; }
00173   Trailer& getTrailer() { return m_trailer; }
00174 
00175   bool hasValidStructure(int& field) const
00176   { field = m_field;
00177     return m_validStructure;
00178   }
00179 
00180   int bodyLength( int beginStringField = FIELD::BeginString, 
00181                   int bodyLengthField = FIELD::BodyLength, 
00182                   int checkSumField = FIELD::CheckSum ) const
00183   { return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)
00184            + calculateLength(beginStringField, bodyLengthField, checkSumField)
00185            + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);
00186   }
00187 
00188   int checkSum( int checkSumField = FIELD::CheckSum ) const
00189   { return ( m_header.calculateTotal(checkSumField)
00190              + calculateTotal(checkSumField)
00191              + m_trailer.calculateTotal(checkSumField) ) % 256;
00192   }
00193 
00194   bool isAdmin() const
00195   { 
00196     MsgType msgType;
00197     if( m_header.isSetField(msgType) )
00198     {
00199       m_header.getField( msgType );
00200       return isAdminMsgType( msgType );
00201     }
00202     return false;
00203   }
00204 
00205   bool isApp() const
00206   { 
00207     MsgType msgType;
00208     if( m_header.isSetField(msgType) )
00209     {
00210       m_header.getField( msgType );
00211       return !isAdminMsgType( msgType );
00212     }
00213     return false;
00214   }
00215 
00216   bool isEmpty()
00217   { return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }
00218 
00219   void clear()
00220   { 
00221     m_field = 0;
00222     m_header.clear();
00223     FieldMap::clear();
00224     m_trailer.clear();
00225   }
00226 
00227   static bool isAdminMsgType( const MsgType& msgType )
00228   { if ( msgType.getValue().length() != 1 ) return false;
00229     return strchr
00230            ( "0A12345",
00231              msgType.getValue().c_str() [ 0 ] ) != 0;
00232   }
00233 
00234   static bool isHeaderField( int field );
00235   static bool isHeaderField( const FieldBase& field,
00236                              const DataDictionary* pD = 0 );
00237 
00238   static bool isTrailerField( int field );
00239   static bool isTrailerField( const FieldBase& field,
00240                               const DataDictionary* pD = 0 );
00241 
00243   SessionID getSessionID( const std::string& qualifier = "" )
00244   throw( FieldNotFound );
00246   void setSessionID( const SessionID& sessionID );
00247 
00248 private:
00249   FieldBase Message::extractField
00250   ( const std::string& string, std::string::size_type& pos,
00251     const DataDictionary* pDD = 0, const Group* pGroup = 0)
00252   { QF_STACK_PUSH(Message::extractField)
00253 
00254     std::string::size_type equalSign
00255       = string.find_first_of( '=', pos );
00256     if( equalSign == std::string::npos )
00257       throw InvalidMessage("Equal sign not found in field");
00258 
00259     int field = atol(string.substr( pos, equalSign - pos ).c_str());
00260 
00261     std::string::size_type soh =
00262       string.find_first_of( '\001', equalSign + 1 );
00263     if ( soh == std::string::npos )
00264       throw InvalidMessage("SOH not found at end of field");
00265 
00266     if ( pDD && pDD->isDataField(field) )
00267     {
00268       std::string fieldLength;
00269       // Assume length field is 1 less.
00270       int lenField = field - 1;
00271       // Special case for Signature which violates above assumption.
00272       if ( field == 89 ) lenField = 93;
00273 
00274       if ( pGroup && pGroup->isSetField( lenField ) )
00275       {
00276         fieldLength = pGroup->getField( lenField);
00277         soh = equalSign + 1 + atol( fieldLength.c_str() );
00278       }
00279       else if ( isSetField( lenField ) )
00280       {
00281         fieldLength = getField( lenField );
00282         soh = equalSign + 1 + atol( fieldLength.c_str() );
00283       }
00284     }
00285 
00286     pos = soh + 1;
00287     return FieldBase (
00288       field,
00289       string.substr( equalSign + 1, soh - ( equalSign + 1 ) ) );
00290 
00291     QF_STACK_POP
00292   }
00293 
00294   void validate();
00295   std::string toXMLFields(const FieldMap& fields, int space) const;
00296 
00297 protected:
00298   mutable FieldMap m_header;
00299   mutable FieldMap m_trailer;
00300   bool m_validStructure;
00301   int m_field;
00302   static std::auto_ptr<DataDictionary> s_dataDictionary;
00303 };
00306 inline std::ostream& operator <<
00307 ( std::ostream& stream, const Message& message )
00308 {
00309   std::string str;
00310   stream << message.toString( str );
00311   return stream;
00312 }
00313 
00315 inline MsgType identifyType( const std::string& message )
00316 throw( MessageParseError )
00317 {
00318   std::string::size_type pos = message.find( "\00135=" );
00319   if ( pos == std::string::npos ) throw MessageParseError();
00320 
00321   std::string::size_type startValue = pos + 4;
00322   std::string::size_type soh = message.find_first_of( '\001', startValue );
00323   if ( soh == std::string::npos ) throw MessageParseError();
00324 
00325   std::string value = message.substr( startValue, soh - startValue );
00326   return MsgType( value );
00327 }
00328 }
00329 
00330 #endif //FIX_MESSAGE

Generated on Mon Jul 24 19:36:29 2006 for QuickFIX by doxygen 1.3.6-20040222 written by Dimitri van Heesch, © 1997-2001