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 == ApplVerId_FIX40 )
00253 return ApplVerID(ApplVerID_FIX40);
00254 if( value == ApplVerId_FIX41 )
00255 return ApplVerID(ApplVerID_FIX41);
00256 if( value == ApplVerId_FIX42 )
00257 return ApplVerID(ApplVerID_FIX42);
00258 if( value == ApplVerId_FIX43 )
00259 return ApplVerID(ApplVerID_FIX43);
00260 if( value == ApplVerId_FIX44 )
00261 return ApplVerID(ApplVerID_FIX44);
00262 if( value == ApplVerId_FIX50 )
00263 return ApplVerID(ApplVerID_FIX50);
00264 return ApplVerID(ApplVerID(value));
00265
00266 QF_STACK_POP
00267 }
00268
00269 static BeginString toBeginString( const ApplVerID& applVerID )
00270 {
00271 if( applVerID == ApplVerID_FIX40 )
00272 return BeginString(BeginString_FIX40);
00273 else if( applVerID == ApplVerID_FIX41 )
00274 return BeginString(BeginString_FIX41);
00275 else if( applVerID == ApplVerID_FIX42 )
00276 return BeginString(BeginString_FIX42);
00277 else if( applVerID == ApplVerID_FIX43 )
00278 return BeginString(BeginString_FIX43);
00279 else if( applVerID == ApplVerID_FIX44 )
00280 return BeginString(BeginString_FIX44);
00281 else if( applVerID == ApplVerID_FIX50 )
00282 return BeginString(ApplVerId_FIX50);
00283 else
00284 return BeginString("");
00285 }
00286
00287 static bool isHeaderField( int field );
00288 static bool isHeaderField( const FieldBase& field,
00289 const DataDictionary* pD = 0 );
00290
00291 static bool isTrailerField( int field );
00292 static bool isTrailerField( const FieldBase& field,
00293 const DataDictionary* pD = 0 );
00294
00296 SessionID getSessionID( const std::string& qualifier = "" ) const
00297 throw( FieldNotFound );
00299 void setSessionID( const SessionID& sessionID );
00300
00301 private:
00302 FieldBase extractField
00303 ( const std::string& string, std::string::size_type& pos,
00304 const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
00305 const Group* pGroup = 0)
00306 { QF_STACK_PUSH(extractField)
00307
00308 std::string::size_type equalSign
00309 = string.find_first_of( '=', pos );
00310 if( equalSign == std::string::npos )
00311 throw InvalidMessage("Equal sign not found in field");
00312
00313 char* pEnd = 0;
00314 int field = strtol( string.c_str() + pos, &pEnd, 0 );
00315
00316 std::string::size_type soh =
00317 string.find_first_of( '\001', equalSign + 1 );
00318 if ( soh == std::string::npos )
00319 throw InvalidMessage("SOH not found at end of field");
00320
00321 if ( (pSessionDD && pSessionDD->isDataField(field)) || (pAppDD && pAppDD->isDataField(field)) )
00322 {
00323 std::string fieldLength;
00324
00325 int lenField = field - 1;
00326
00327 if ( field == 89 ) lenField = 93;
00328
00329 if ( pGroup && pGroup->isSetField( lenField ) )
00330 {
00331 fieldLength = pGroup->getField( lenField );
00332 soh = equalSign + 1 + atol( fieldLength.c_str() );
00333 }
00334 else if ( isSetField( lenField ) )
00335 {
00336 fieldLength = getField( lenField );
00337 soh = equalSign + 1 + atol( fieldLength.c_str() );
00338 }
00339 }
00340
00341 pos = soh + 1;
00342 return FieldBase (
00343 field,
00344 string.substr( equalSign + 1, soh - ( equalSign + 1 ) ) );
00345
00346 QF_STACK_POP
00347 }
00348
00349 void validate();
00350 std::string toXMLFields(const FieldMap& fields, int space) const;
00351
00352 protected:
00353 mutable FieldMap m_header;
00354 mutable FieldMap m_trailer;
00355 bool m_validStructure;
00356 int m_field;
00357 static std::auto_ptr<DataDictionary> s_dataDictionary;
00358 };
00361 inline std::ostream& operator <<
00362 ( std::ostream& stream, const Message& message )
00363 {
00364 std::string str;
00365 stream << message.toString( str );
00366 return stream;
00367 }
00368
00370 inline MsgType identifyType( const std::string& message )
00371 throw( MessageParseError )
00372 {
00373 std::string::size_type pos = message.find( "\00135=" );
00374 if ( pos == std::string::npos ) throw MessageParseError();
00375
00376 std::string::size_type startValue = pos + 4;
00377 std::string::size_type soh = message.find_first_of( '\001', startValue );
00378 if ( soh == std::string::npos ) throw MessageParseError();
00379
00380 std::string value = message.substr( startValue, soh - startValue );
00381 return MsgType( value );
00382 }
00383 }
00384
00385 #endif //FIX_MESSAGE