Message.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. /* -*- C++ -*- */
  2. /****************************************************************************
  3. ** Copyright (c) 2001-2014
  4. **
  5. ** This file is part of the QuickFIX FIX Engine
  6. **
  7. ** This file may be distributed under the terms of the quickfixengine.org
  8. ** license as defined by quickfixengine.org and appearing in the file
  9. ** LICENSE included in the packaging of this file.
  10. **
  11. ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
  12. ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13. **
  14. ** See http://www.quickfixengine.org/LICENSE for licensing information.
  15. **
  16. ** Contact ask@quickfixengine.org if any conditions of this licensing are
  17. ** not clear to you.
  18. **
  19. ****************************************************************************/
  20. #ifndef FIX_MESSAGE
  21. #define FIX_MESSAGE
  22. #ifdef _MSC_VER
  23. #pragma warning( disable: 4786 )
  24. #endif
  25. #include "FieldMap.h"
  26. #include "Fields.h"
  27. #include "Group.h"
  28. #include "SessionID.h"
  29. #include "DataDictionary.h"
  30. #include "Values.h"
  31. #include <vector>
  32. #include <memory>
  33. namespace FIX
  34. {
  35. static int const headerOrder[] =
  36. {
  37. FIELD::BeginString,
  38. FIELD::BodyLength,
  39. FIELD::MsgType
  40. };
  41. class Header : public FieldMap
  42. {
  43. public:
  44. Header() : FieldMap(message_order( message_order::header ) )
  45. {}
  46. };
  47. class Trailer : public FieldMap
  48. {
  49. public:
  50. Trailer() : FieldMap(message_order( message_order::trailer ) )
  51. {}
  52. };
  53. /**
  54. * Base class for all %FIX messages.
  55. *
  56. * A message consists of three field maps. One for the header, the body,
  57. * and the trailer.
  58. */
  59. class Message : public FieldMap
  60. {
  61. friend class DataDictionary;
  62. friend class Session;
  63. enum field_type { header, body, trailer };
  64. public:
  65. Message();
  66. /// Construct a message from a string
  67. Message( const std::string& string, bool validate = true )
  68. throw( InvalidMessage );
  69. /// Construct a message from a string using a data dictionary
  70. Message( const std::string& string, const FIX::DataDictionary& dataDictionary,
  71. bool validate = true )
  72. throw( InvalidMessage );
  73. /// Construct a message from a string using a session and application data dictionary
  74. Message( const std::string& string, const FIX::DataDictionary& sessionDataDictionary,
  75. const FIX::DataDictionary& applicationDataDictionary, bool validate = true )
  76. throw( InvalidMessage );
  77. Message( const Message& copy )
  78. : FieldMap( copy )
  79. {
  80. m_header = copy.m_header;
  81. m_trailer = copy.m_trailer;
  82. m_validStructure = copy.m_validStructure;
  83. m_field = copy.m_field;
  84. }
  85. /// Set global data dictionary for encoding messages into XML
  86. static bool InitializeXML( const std::string& string );
  87. void addGroup( const FIX::Group& group )
  88. { FieldMap::addGroup( group.field(), group ); }
  89. void replaceGroup( unsigned num, const FIX::Group& group )
  90. { FieldMap::replaceGroup( num, group.field(), group ); }
  91. Group& getGroup( unsigned num, FIX::Group& group ) const throw( FieldNotFound )
  92. { group.clear();
  93. return static_cast < Group& >
  94. ( FieldMap::getGroup( num, group.field(), group ) );
  95. }
  96. void removeGroup( unsigned num, const FIX::Group& group )
  97. { FieldMap::removeGroup( num, group.field() ); }
  98. void removeGroup( const FIX::Group& group )
  99. { FieldMap::removeGroup( group.field() ); }
  100. bool hasGroup( const FIX::Group& group ) const
  101. { return FieldMap::hasGroup( group.field() ); }
  102. bool hasGroup( unsigned num, const FIX::Group& group ) const
  103. { return FieldMap::hasGroup( num, group.field() ); }
  104. protected:
  105. // Constructor for derived classes
  106. Message( const BeginString& beginString, const MsgType& msgType )
  107. : m_validStructure( true )
  108. {
  109. m_header.setField( beginString );
  110. m_header.setField( msgType );
  111. }
  112. public:
  113. /// Get a string representation of the message
  114. std::string toString( int beginStringField = FIELD::BeginString,
  115. int bodyLengthField = FIELD::BodyLength,
  116. int checkSumField = FIELD::CheckSum ) const;
  117. /// Get a string representation without making a copy
  118. std::string& toString( std::string&,
  119. int beginStringField = FIELD::BeginString,
  120. int bodyLengthField = FIELD::BodyLength,
  121. int checkSumField = FIELD::CheckSum ) const;
  122. /// Get a XML representation of the message
  123. std::string toXML() const;
  124. /// Get a XML representation without making a copy
  125. std::string& toXML( std::string& ) const;
  126. /**
  127. * Add header informations depending on a source message.
  128. * This can be used to add routing informations like OnBehalfOfCompID
  129. * and DeliverToCompID to a message.
  130. */
  131. void reverseRoute( const Header& );
  132. /**
  133. * Set a message based on a string representation
  134. * This will fill in the fields on the message by parsing out the string
  135. * that is passed in. It will return true on success and false
  136. * on failure.
  137. */
  138. void setString( const std::string& string )
  139. throw( InvalidMessage )
  140. { setString(string, true); }
  141. void setString( const std::string& string, bool validate )
  142. throw( InvalidMessage )
  143. { setString(string, validate, 0); }
  144. void setString( const std::string& string,
  145. bool validate,
  146. const FIX::DataDictionary* pDataDictionary )
  147. throw( InvalidMessage )
  148. { setString(string, validate, pDataDictionary, pDataDictionary); }
  149. void setString( const std::string& string,
  150. bool validate,
  151. const FIX::DataDictionary* pSessionDataDictionary,
  152. const FIX::DataDictionary* pApplicationDataDictionary )
  153. throw( InvalidMessage );
  154. void setGroup( const std::string& msg, const FieldBase& field,
  155. const std::string& string, std::string::size_type& pos,
  156. FieldMap& map, const DataDictionary& dataDictionary );
  157. /**
  158. * Set a messages header from a string
  159. * This is an optimization that can be used to get useful information
  160. * from the header of a FIX string without parsing the whole thing.
  161. */
  162. bool setStringHeader( const std::string& string );
  163. /// Getter for the message header
  164. const Header& getHeader() const { return m_header; }
  165. /// Mutable getter for the message header
  166. Header& getHeader() { return m_header; }
  167. /// Getter for the message trailer
  168. const Trailer& getTrailer() const { return m_trailer; }
  169. /// Mutable getter for the message trailer
  170. Trailer& getTrailer() { return m_trailer; }
  171. bool hasValidStructure(int& field) const
  172. { field = m_field;
  173. return m_validStructure;
  174. }
  175. int bodyLength( int beginStringField = FIELD::BeginString,
  176. int bodyLengthField = FIELD::BodyLength,
  177. int checkSumField = FIELD::CheckSum ) const
  178. { return m_header.calculateLength(beginStringField, bodyLengthField, checkSumField)
  179. + calculateLength(beginStringField, bodyLengthField, checkSumField)
  180. + m_trailer.calculateLength(beginStringField, bodyLengthField, checkSumField);
  181. }
  182. int checkSum( int checkSumField = FIELD::CheckSum ) const
  183. { return ( m_header.calculateTotal(checkSumField)
  184. + calculateTotal(checkSumField)
  185. + m_trailer.calculateTotal(checkSumField) ) % 256;
  186. }
  187. bool isAdmin() const
  188. {
  189. if( m_header.isSetField(FIELD::MsgType) )
  190. {
  191. const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
  192. return isAdminMsgType( msgType );
  193. }
  194. return false;
  195. }
  196. bool isApp() const
  197. {
  198. if( m_header.isSetField(FIELD::MsgType) )
  199. {
  200. const MsgType& msgType = FIELD_GET_REF( m_header, MsgType );
  201. return !isAdminMsgType( msgType );
  202. }
  203. return false;
  204. }
  205. bool isEmpty()
  206. { return m_header.isEmpty() && FieldMap::isEmpty() && m_trailer.isEmpty(); }
  207. void clear()
  208. {
  209. m_field = 0;
  210. m_header.clear();
  211. FieldMap::clear();
  212. m_trailer.clear();
  213. }
  214. static bool isAdminMsgType( const MsgType& msgType )
  215. { if ( msgType.getValue().length() != 1 ) return false;
  216. return strchr
  217. ( "0A12345",
  218. msgType.getValue().c_str() [ 0 ] ) != 0;
  219. }
  220. static ApplVerID toApplVerID(const BeginString& value)
  221. {
  222. if( value == BeginString_FIX40 )
  223. return ApplVerID(ApplVerID_FIX40);
  224. if( value == BeginString_FIX41 )
  225. return ApplVerID(ApplVerID_FIX41);
  226. if( value == BeginString_FIX42 )
  227. return ApplVerID(ApplVerID_FIX42);
  228. if( value == BeginString_FIX43 )
  229. return ApplVerID(ApplVerID_FIX43);
  230. if( value == BeginString_FIX44 )
  231. return ApplVerID(ApplVerID_FIX44);
  232. if( value == BeginString_FIX50 )
  233. return ApplVerID(ApplVerID_FIX50);
  234. if( value == "FIX.5.0SP1" )
  235. return ApplVerID(ApplVerID_FIX50SP1);
  236. if( value == "FIX.5.0SP2" )
  237. return ApplVerID(ApplVerID_FIX50SP2);
  238. return ApplVerID(ApplVerID(value));
  239. }
  240. static BeginString toBeginString( const ApplVerID& applVerID )
  241. {
  242. if( applVerID == ApplVerID_FIX40 )
  243. return BeginString(BeginString_FIX40);
  244. else if( applVerID == ApplVerID_FIX41 )
  245. return BeginString(BeginString_FIX41);
  246. else if( applVerID == ApplVerID_FIX42 )
  247. return BeginString(BeginString_FIX42);
  248. else if( applVerID == ApplVerID_FIX43 )
  249. return BeginString(BeginString_FIX43);
  250. else if( applVerID == ApplVerID_FIX44 )
  251. return BeginString(BeginString_FIX44);
  252. else if( applVerID == ApplVerID_FIX50 )
  253. return BeginString(BeginString_FIX50);
  254. else if( applVerID == ApplVerID_FIX50SP1 )
  255. return BeginString(BeginString_FIX50);
  256. else if( applVerID == ApplVerID_FIX50SP2 )
  257. return BeginString(BeginString_FIX50);
  258. else
  259. return BeginString("");
  260. }
  261. static bool isHeaderField( int field );
  262. static bool isHeaderField( const FieldBase& field,
  263. const DataDictionary* pD = 0 );
  264. static bool isTrailerField( int field );
  265. static bool isTrailerField( const FieldBase& field,
  266. const DataDictionary* pD = 0 );
  267. /// Returns the session ID of the intended recipient
  268. SessionID getSessionID( const std::string& qualifier = "" ) const
  269. throw( FieldNotFound );
  270. /// Sets the session ID of the intended recipient
  271. void setSessionID( const SessionID& sessionID );
  272. private:
  273. FieldBase extractField(
  274. const std::string& string, std::string::size_type& pos,
  275. const DataDictionary* pSessionDD = 0, const DataDictionary* pAppDD = 0,
  276. const Group* pGroup = 0);
  277. static bool IsDataField(
  278. int field,
  279. const DataDictionary* pSessionDD,
  280. const DataDictionary* pAppDD )
  281. {
  282. if( (pSessionDD && pSessionDD->isDataField( field )) ||
  283. (pAppDD && pAppDD != pSessionDD && pAppDD->isDataField( field )) )
  284. {
  285. return true;
  286. }
  287. return false;
  288. }
  289. void validate();
  290. std::string toXMLFields(const FieldMap& fields, int space) const;
  291. protected:
  292. mutable Header m_header;
  293. mutable Trailer m_trailer;
  294. bool m_validStructure;
  295. int m_field;
  296. static std::auto_ptr<DataDictionary> s_dataDictionary;
  297. };
  298. /*! @} */
  299. inline std::ostream& operator <<
  300. ( std::ostream& stream, const Message& message )
  301. {
  302. std::string str;
  303. stream << message.toString( str );
  304. return stream;
  305. }
  306. /// Parse the type of a message from a string.
  307. inline MsgType identifyType( const std::string& message )
  308. throw( MessageParseError )
  309. {
  310. std::string::size_type pos = message.find( "\001" "35=" );
  311. if ( pos == std::string::npos ) throw MessageParseError();
  312. std::string::size_type startValue = pos + 4;
  313. std::string::size_type soh = message.find_first_of( '\001', startValue );
  314. if ( soh == std::string::npos ) throw MessageParseError();
  315. std::string value = message.substr( startValue, soh - startValue );
  316. return MsgType( value );
  317. }
  318. }
  319. #endif //FIX_MESSAGE