libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
messages.hpp
Go to the documentation of this file.
1 #ifndef ISIMUD_EXCHANGES_FIX_common_MESSAGES_HPP
2 #define ISIMUD_EXCHANGES_FIX_common_MESSAGES_HPP
3 /******************************************************************************
4 ** Copyright © 2015 by J.M.McGuiness, isimud@hussar.me.uk
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public
17 ** License along with this library; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20 
22 
23 #include "core/memops.hpp"
24 #include "core/ttypes.hpp"
25 
26 #include <boost/mpl/assert.hpp>
27 #include <boost/date_time/posix_time/posix_time.hpp>
28 
29 #include <numeric>
30 #include <cassert>
31 #include <cstring>
32 
33 namespace isimud { namespace ISIMUD_VER_NAMESPACE { namespace exchanges { namespace FIX { namespace common {
34 
35 struct logon_args_t {
36 };
37 struct logoff_args_t {
38 };
39 
40 template<
41  class MsgVer ///< The version of FIX protocol to support.
42 >
43 class Header {
44 public:
45  using msg_version_t=MsgVer;
46  using element_type=char;
47  using pointer=element_type *;
48  using const_pointer=element_type const *;
49  using size_type=std::size_t;
51 
52  enum : bool {
53  has_static_size=false ///< The message is statically-sized, not dynamically, so sizeof(the derived message-type) is the amount to copy, i.e. length() returns sizeof(the derived message-type).
54  };
55  enum : std::size_t {
56  header_t_size=msg_version_t::fix_template_body_length_offset+sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)+1
57  };
58 
59  /// Create a FIX message from an array of chars read from a socket or elsewhere.
60  /**
61  In debug builds the validity of the FIX message is checked.
62 
63  \param b The array of chars that must comprise a valid FIX message.
64  */
65  constexpr __stdcall Header() noexcept(true);
66 
67  /// Determine the total size of the referenced message.
68  /**
69  The referenced message must be valid.
70 
71  \return The size of the whole the message, including the version, size (itself) and checksum fields.
72 
73  \see size()
74  */
75  constexpr size_type length() const noexcept(true);
76 
77  /// Determine if the specified tag is in the referenced message.
78  /**
79  \param field The field to be found. Note that the range must contain the field otherwise the behaviour shall be undefined.
80  \return True if the specified tag was found in the referenced message.
81  */
82  template<FieldsFast field>
83  constexpr field_str_range_t __fastcall find() noexcept(true);
84  /// Determine if the specified tag is in the referenced message.
85  /**
86  \param field The field to be found. Note that the range must contain the field otherwise the behaviour shall be undefined.
87  \return True if the specified tag was found in the referenced message.
88  */
89  template<FieldsFast field>
90  constexpr field_str_const_range_t __fastcall find() const noexcept(true);
91 
92  constexpr field_str_const_range_t __fastcall find_ExDestination() const noexcept(true);
93  constexpr ExDestination_t __fastcall find_MIC() const noexcept(true);
94 
95  MsgTypes type() const noexcept(true) __attribute__((pure));
96 
97  /// Verify that the referenced FIX message is valid.
98  /**
99  \return True is the referenced FIX message is valid, false otherwise.
100  */
101  constexpr bool is_valid() const noexcept(true);
102 
103  /// Generate the checksum for the referenced FIX message.
104  /**
105  \param body_len The length of the body of the referenced FIX message.
106  \return The computed check sum.
107  */
108  checksum_t
109  generate_checksum(size_type body_len) const noexcept(true);
110 
111  /// Verify that the checksum of the referenced FIX message is valid.
112  /**
113  \param body_len The length of the body of the referenced FIX message.
114  \param start_of_checksum_value A pointer to that start of the checksum value embedded in the referenced FIX message.
115  \return True is the checksum of the referenced FIX message is valid, false otherwise.
116  */
117  constexpr bool is_checksum_valid(size_type body_len, const_pointer start_of_checksum_value) const noexcept(true);
118 
119 protected:
120  static_assert(max_size_of_fix_message>0, "Buffer must be non-zero.");
121  ALIGN_TO_L1_CACHE char begin_string[sizeof(msg_version_t::MsgVer)-1];
125  underlying_fix_data_buffer data_;
126 
127  template<MsgTypes MsgType> constexpr underlying_fix_data_buffer::iterator
128  set_header() noexcept(true);
129  template<
130  MsgTypes MsgType
132  set_sequence_num_int(SeqNum_t seq_num) noexcept(true);
133  template<
134  MsgTypes MsgType,
135  class SrcMsg,
137  > constexpr Ret
138  set_sequence_num(SrcMsg const &msg) noexcept(true);
139 } __attribute__((packed));
140 
141 /// The basic, underlying type used to implement FIX message reading.
142 /**
143 */
144 template<
145  class MsgVer ///< The version of FIX protocol to support.
146 >
147 class Message : public Header<MsgVer> {
148 public:
149  using Header_t=Header<MsgVer>;
150  using msg_version_t=typename Header_t::msg_version_t;
151  using element_type=typename Header_t::element_type;
152  using pointer=typename Header_t::pointer;
153  using const_pointer=typename Header_t::const_pointer;
154  using size_type=typename Header_t::size_type;
155  using RejectCode_t=int;
156 
157  static inline constexpr MsgTypes static_type=msg_version_t::msg_type::tag;
158  static inline constexpr const RejectCode_t unknown_msg=1;
159 
160  /// Wrap a FIX message contained in an array of chars that has been written into from a socket or elsewhere.
161  /**
162  \param b The array of chars that must comprise a valid FIX message which is not automatically checked.
163  */
164  explicit constexpr __stdcall Message() noexcept(true);
165  explicit constexpr __stdcall Message(logon_args_t const &) noexcept(true);
166  explicit constexpr __stdcall Message(logoff_args_t const &) noexcept(true);
167  explicit constexpr __stdcall Message(RejectCode_t const &) noexcept(true);
168  /// Create a NewOrderSIngle.
169  __stdcall Message(SeqNum_t seqNum, ClientOrderID_t const &clID, OrderType const oT, TIF const t, Side const s, SecurityID_t instID, Quantity_t ordQty, Price_t p, ExDestination_t mic) noexcept(true);
170  /// Create an ExecutionReport.
171  __stdcall Message(SeqNum_t seqNum, ClientOrderID_t const &clID, ExecType eT, Price_t const price, SecurityID_t instID, Side s, Quantity_t execdQty, Quantity_t leavesQty, ExDestination_t mic) noexcept(true);
172  /// Create a message from the source message, into the underlying buffer.
173  /**
174  In debug builds the validity of the FIX message is checked.
175 
176  If an error is generated, then this function will need to be specialised for the particular SrcMsg.
177 
178  \param msg The source message from which the target message should be created.
179  */
180  template<
181  class SrcMsg ///< The type of message from which this FIX message should be created. E.g. a MIT-type, BATSBOE, etc.
182  > __stdcall explicit
183  Message(SrcMsg const &msg)=delete;
184  /// Create a message from the source message, into the underlying buffer.
185  /**
186  In debug builds the validity of the FIX message is checked.
187 
188  If an error is generated, then this function will need to be specialised for the particular SrcMsg.
189 
190  \param msg The source message from which the target message should be created.
191  \param ref_data The reference data to map from exchange-based instrument identifiers to client-based symbology.
192  */
193  template<
194  class SrcMsg, ///< The type of message from which this FIX message should be created. E.g. a MIT-type, BATSBOE, etc.
195  class RefData
196  > __stdcall
197  Message(SrcMsg const &msg, RefData const &ref_data)=delete;
198 
199 /*
200  \todo The idea is that the fields that we wish to comprise the FIX message from are passed as a set of template parameters, so that the FIX message can be largely constructed at compile-time, thus being highly efficient.
201 */
202  template<
203  class RefData,
204  class ... Fields
205  >
206  Message(RefData const &ref_data, Fields ... fields);
207 
208  /// Determine the size of the referenced message.
209  /**
210  The referenced message must be valid.
211 
212  \return The size of the body of the message, excluding the version, size (itself) and checksum fields.
213 
214  \see length()
215  */
216  constexpr size_type __fastcall size() const noexcept(true);
217 
218  /// Determine if the specified tag is in the referenced message.
219  /**
220  \param field The field to be found. Note that the range must contain the field otherwise the behaviour shall be undefined.
221  \return True if the specified tag was found in the referenced message.
222  */
223  template<FieldsFast field>
224  constexpr bool __fastcall search() const noexcept(true);
225 
226  /// Verify that the referenced FIX message is valid.
227  /**
228  \return True is the referenced FIX message is valid, false otherwise.
229  */
230  constexpr bool is_valid() const noexcept(true);
231 
232  std::string to_string() const noexcept(false);
233 
234  constexpr ClientOrderID_t clientOrderID() const noexcept(true);
235  constexpr Side side() const noexcept(true);
236  constexpr Price_t limitPrice() const noexcept(true);
237  constexpr Quantity_t orderQty() const noexcept(true);
238  constexpr void orderQty(Quantity_t q) noexcept(true);
239  constexpr SecurityID_t instrumentID() const noexcept(true);
240 
241  template<class OutIter>
242  OutIter write_ClOrdID(ClientOrderID_t const &clID, OutIter data) noexcept(true);
243  template<class OutIter>
244  OutIter write_TransactTime(OutIter data) noexcept(true);
245  template<class OutIter>
246  OutIter write_ExDest(ExDestination_t mic, OutIter data) noexcept(true);
247 
248  template<FieldsFast field>
251 
252 protected:
253  constexpr void finalise_msg(underlying_fix_data_buffer::iterator) noexcept(true);
254 } __attribute__((packed));
255 
256 template<class MsgVer> std::ostream &
257 operator<<(std::ostream &os, Message<MsgVer> const &m);
258 
259 } } } } }
260 
261 #include "messages_impl.hpp"
262 
263 #endif