00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
00270 int lenField = field - 1;
00271
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