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 "Values.h"
00036 #include <vector>
00037 #include <memory>
00038
00039 namespace FIX
00040 {
00041 typedef FieldMap Header;
00042 typedef FieldMap Trailer;
00043
00044 static int const headerOrder[] =
00045 {
00046 FIELD::BeginString,
00047 FIELD::BodyLength,
00048 FIELD::MsgType
00049 };
00050
00057 class Message : public FieldMap
00058 {
00059 friend class DataDictionary;
00060 friend class Session;
00061
00062 enum field_type { header, body, trailer };
00063
00064 public:
00065 Message();
00066
00068 Message( const std::string& string, bool validate = true )
00069 throw( InvalidMessage );
00070
00072 Message( const std::string& string, const FIX::DataDictionary& dataDictionary,
00073 bool validate = true )
00074 throw( InvalidMessage );
00075
00077 Message( const std::string& string, const FIX::DataDictionary& sessionDataDictionary,
00078 const FIX::DataDictionary& applicationDataDictionary, bool validate = true )
00079 throw( InvalidMessage );
00080
00081 Message( const Message& copy )
00082 : FieldMap( copy ),
00083 m_header( message_order( message_order::header ) ),
00084 m_trailer( message_order( message_order::trailer ) )
00085 {
00086 m_header = copy.m_header;
00087 m_trailer = copy.m_trailer;
00088 m_validStructure = copy.m_validStructure;
00089 m_field = copy.m_field;
00090 }
00091
00093 static bool InitializeXML( const std::string& string );
00094
00095 void addGroup( FIX::Group& group )
00096 { FieldMap::addGroup( group.field(), group ); }
00097
00098 void replaceGroup( unsigned num, FIX::Group& group )
00099 { FieldMap::replaceGroup( num, group.field(), group ); }
00100
00101 Group& getGroup( unsigned num, FIX::Group& group ) const throw( FieldNotFound )
00102 { group.clear();
00103 return static_cast < Group& >
00104 ( FieldMap::getGroup( num, group.field(), group ) );
00105 }
00106
00107 void removeGroup( unsigned num, FIX::Group& group )
00108 { FieldMap::removeGroup( num, group.field() ); }
00109 void removeGroup( FIX::Group& group )
00110 { FieldMap::removeGroup( group.field() ); }
00111
00112 bool hasGroup( const FIX::Group& group ) const
00113 { return FieldMap::hasGroup( group.field() ); }
00114 bool hasGroup( unsigned num, FIX::Group& group ) const
00115 { return FieldMap::hasGroup( num, group.field() ); }
00116
00117 protected:
00118
00119 Message( const BeginString& beginString, const MsgType& msgType )
00120 : m_header( message_order( message_order::header ) ),
00121 m_trailer( message_order( message_order::trailer ) ),
00122 m_validStructure( true )
00123 {
00124 m_header.setField( beginString );
00125 m_header.setField( msgType );
00126 }
00127
00128 public:
00130 std::string toString( int beginStringField = FIELD::BeginString,
00131 int bodyLengthField = FIELD::BodyLength,
00132 int checkSumField = FIELD::CheckSum ) const;
00134 std::string& toString( std::string&,
00135 int beginStringField = FIELD::BeginString,
00136 int bodyLengthField = FIELD::BodyLength,
00137 int checkSumField = FIELD::CheckSum ) const;
00139 std::string toXML() const;
00141 std::string& toXML( std::string& ) const;
00142
00148 void reverseRoute( const Header& );
00149
00156 void setString( const std::string& string )
00157 { setString(string, true); }
00158 void setString( const std::string& string, bool validate )
00159 { setString(string, validate, 0); }
00160 void setString( const std::string& string,
00161 bool validate,
00162 const FIX::DataDictionary* pDataDictionary )
00163 throw( InvalidMessage )
00164 { setString(string, validate, pDataDictionary, pDataDictionary); }
00165
00166 void setString( const std::string& string,
00167 bool validate,
00168 const FIX::DataDictionary* pSessionDataDictionary,
00169 const FIX::DataDictionary* pApplicationDataDictionary )
00170 throw( InvalidMessage );
00171
00172 void setGroup( const std::string& msg, const FieldBase& field,
00173 const std::string& string, std::string::size_type& pos,
00174 FieldMap& map, const DataDictionary& dataDictionary );
00175
00181 bool setStringHeader( const std::string& string );
00182
00184 const Header& getHeader() const { return m_header; }
00186 Header& getHeader() { return m_header; }
00188 const Header& getTrailer() const { return m_trailer; }
00190 Trailer& getTrailer() { return m_trailer; }
00191
00192 bool hasValidStructure(int& field) const
00193 { field = m_field;
00194 return m_validStructure;
00195 }
00196
00197 int bodyLength( int beginStringField = FIELD::BeginString,
00198 int bodyLengthField = FIELD::BodyLength,
00199 int checkSumField = FIELD::CheckSum ) const
00200 { return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)
00201 + calculateLength(beginStringField, bodyLengthField, checkSumField)
00202 + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);
00203 }
00204
00205 int checkSum( int checkSumField = FIELD::CheckSum ) const
00206 { return ( m_header.calculateTotal(checkSumField)
00207 + calculateTotal(checkSumField)
00208 + m_trailer.calculateTotal(checkSumField) ) % 256;
00209 }
00210
00211 bool isAdmin() const
00212 {
00213 if( m_header.isSetField(FIELD::MsgType) )
00214 {
00215 const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
00216 return isAdminMsgType( msgType );
00217 }
00218 return false;
00219 }
00220
00221 bool isApp() const
00222 {
00223 if( m_header.isSetField(FIELD::MsgType) )
00224 {
00225 const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
00226 return !isAdminMsgType( msgType );
00227 }
00228 return false;
00229 }
00230
00231 bool isEmpty()
00232 { return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }
00233
00234 void clear()
00235 {
00236 m_field = 0;
00237 m_header.clear();
00238 FieldMap::clear();
00239 m_trailer.clear();
00240 }
00241
00242 static bool isAdminMsgType( const MsgType& msgType )
00243 { if ( msgType.getValue().length() != 1 ) return false;
00244 return strchr
00245 ( "0A12345",
00246 msgType.getValue().c_str() [ 0 ] ) != 0;
00247 }
00248
00249 static ApplVerID toApplVerID(const BeginString& value)
00250 { QF_STACK_PUSH(SessionFactory::toApplVerID)
00251
00252 if( value == BeginString_FIX40 )
00253 return ApplVerID(ApplVerID_FIX40);
00254 if( value == BeginString_FIX41 )
00255 return ApplVerID(ApplVerID_FIX41);
00256 if( value == BeginString_FIX42 )
00257 return ApplVerID(ApplVerID_FIX42);
00258 if( value == BeginString_FIX43 )
00259 return ApplVerID(ApplVerID_FIX43);
00260 if( value == BeginString_FIX44 )
00261 return ApplVerID(ApplVerID_FIX44);
00262 if( value == BeginString_FIX50 )
00263 return ApplVerID(ApplVerID_FIX50);
00264 if( value == "FIX.5.0SP1" )
00265 return ApplVerID(ApplVerID_FIX50SP1);
00266 if( value == "FIX.5.0SP2" )
00267 return ApplVerID(ApplVerID_FIX50SP2);
00268 return ApplVerID(ApplVerID(value));
00269
00270 QF_STACK_POP
00271 }
00272
00273 static BeginString toBeginString( const ApplVerID& applVerID )
00274 {
00275 if( applVerID == ApplVerID_FIX40 )
00276 return BeginString(BeginString_FIX40);
00277 else if( applVerID == ApplVerID_FIX41 )
00278 return BeginString(BeginString_FIX41);
00279 else if( applVerID == ApplVerID_FIX42 )
00280 return BeginString(BeginString_FIX42);
00281 else if( applVerID == ApplVerID_FIX43 )
00282 return BeginString(BeginString_FIX43);
00283 else if( applVerID == ApplVerID_FIX44 )
00284 return BeginString(BeginString_FIX44);
00285 else if( applVerID == ApplVerID_FIX50 )
00286 return BeginString(BeginString_FIX50);
00287 else if( applVerID == ApplVerID_FIX50SP1 )
00288 return BeginString(BeginString_FIX50);
00289 else if( applVerID == ApplVerID_FIX50SP2 )
00290 return BeginString(BeginString_FIX50);
00291 else
00292 return BeginString("");
00293 }
00294
00295 static bool isHeaderField( int field );
00296 static bool isHeaderField( const FieldBase& field,
00297 const DataDictionary* pD = 0 );
00298
00299 static bool isTrailerField( int field );
00300 static bool isTrailerField( const FieldBase& field,
00301 const DataDictionary* pD = 0 );
00302
00304 SessionID getSessionID( const std::string& qualifier = "" ) const
00305 throw( FieldNotFound );
00307 void setSessionID( const SessionID& sessionID );
00308
00309 private:
00310 FieldBase extractField
00311 ( const std::string& string, std::string::size_type& pos,
00312 const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
00313 const Group* pGroup = 0)
00314 { QF_STACK_PUSH(extractField)
00315
00316 std::string::size_type equalSign
00317 = string.find_first_of( '=', pos );
00318 if( equalSign == std::string::npos )
00319 throw InvalidMessage("Equal sign not found in field");
00320
00321 char* pEnd = 0;
00322 int field = strtol( string.c_str() + pos, &pEnd, 0 );
00323
00324 std::string::size_type soh =
00325 string.find_first_of( '\001', equalSign + 1 );
00326 if ( soh == std::string::npos )
00327 throw InvalidMessage("SOH not found at end of field");
00328
00329 if ( (pSessionDD && pSessionDD->isDataField(field)) || (pAppDD && pAppDD->isDataField(field)) )
00330 {
00331 std::string fieldLength;
00332
00333 int lenField = field - 1;
00334
00335 if ( field == 89 ) lenField = 93;
00336
00337 if ( pGroup && pGroup->isSetField( lenField ) )
00338 {
00339 fieldLength = pGroup->getField( lenField );
00340 soh = equalSign + 1 + atol( fieldLength.c_str() );
00341 }
00342 else if ( isSetField( lenField ) )
00343 {
00344 fieldLength = getField( lenField );
00345 soh = equalSign + 1 + atol( fieldLength.c_str() );
00346 }
00347 }
00348
00349 pos = soh + 1;
00350 return FieldBase (
00351 field,
00352 string.substr( equalSign + 1, soh - ( equalSign + 1 ) ) );
00353
00354 QF_STACK_POP
00355 }
00356
00357 void validate();
00358 std::string toXMLFields(const FieldMap& fields, int space) const;
00359
00360 protected:
00361 mutable FieldMap m_header;
00362 mutable FieldMap m_trailer;
00363 bool m_validStructure;
00364 int m_field;
00365 static std::auto_ptr<DataDictionary> s_dataDictionary;
00366 };
00369 inline std::ostream& operator <<
00370 ( std::ostream& stream, const Message& message )
00371 {
00372 std::string str;
00373 stream << message.toString( str );
00374 return stream;
00375 }
00376
00378 inline MsgType identifyType( const std::string& message )
00379 throw( MessageParseError )
00380 {
00381 std::string::size_type pos = message.find( "\00135=" );
00382 if ( pos == std::string::npos ) throw MessageParseError();
00383
00384 std::string::size_type startValue = pos + 4;
00385 std::string::size_type soh = message.find_first_of( '\001', startValue );
00386 if ( soh == std::string::npos ) throw MessageParseError();
00387
00388 std::string value = message.substr( startValue, soh - startValue );
00389 return MsgType( value );
00390 }
00391 }
00392
00393 #endif //FIX_MESSAGE