21 template<
class MsgVer>
inline constexpr __stdcall
23 using fix_template_to_msg_type_t=underlying_fix_data_buffer::value_type[MsgVer::fix_template_msg_type_offset];
25 MsgVer::fix_template_to_msg_type,
26 reinterpret_cast<fix_template_to_msg_type_t &>(*
begin_string)
30 template<
class MsgVer>
inline constexpr typename Header<MsgVer>::size_type
33 return msg_type_tag-begin_string+body_size+libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size+CheckSumLength+
sizeof(Separator);
37 template<FieldsFast field>
inline
38 constexpr field_str_range_t
__fastcall
41 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
42 pointer field_ptr=
this->body_length_tag;
43 const constexpr size_type field_len=libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
44 field_ptr=
const_cast<pointer>(libjmmcg::strstr_opt(
reinterpret_cast<body_type &>(*field_ptr), libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value));
46 assert(
static_cast<size_type>(field_ptr-start)<
this->length());
48 assert(
static_cast<size_type>(field_ptr-start)<
this->length());
49 pointer end=field_ptr;
50 end=
const_cast<pointer>(libjmmcg::strchr_opt<
Separator>(
reinterpret_cast<body_type &>(*end))+1);
51 assert((end-field_ptr)>0);
52 assert(
static_cast<size_type>(end-field_ptr)<
this->length());
53 assert(
static_cast<size_type>(end-start)<
this->length());
54 return field_str_range_t(field_ptr, end-1);
58 template<FieldsFast field>
inline
59 constexpr field_str_const_range_t
__fastcall
62 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
63 const_pointer field_ptr=
this->body_length_tag;
64 const constexpr size_type field_len=libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
65 field_ptr=libjmmcg::strstr_opt(
reinterpret_cast<body_type &>(*field_ptr), libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value);
67 assert(
static_cast<size_type>(field_ptr-start)<
this->length());
69 assert(
static_cast<size_type>(field_ptr-start)<
this->length());
70 const_pointer end=field_ptr;
71 end=libjmmcg::strchr_opt<
Separator>(
reinterpret_cast<body_type &>(*end));
72 assert((end-field_ptr)>0);
73 assert(
static_cast<size_type>(end-field_ptr)<
this->length());
74 assert(
static_cast<size_type>(end-start)<
this->length());
75 return field_str_const_range_t(field_ptr, end);
78 template<
class MsgVer>
79 constexpr inline field_str_const_range_t
96 return field_str_const_range_t{};
100 template<
class MsgVer>
101 constexpr inline ExDestination_t
103 auto const &exdest=find_ExDestination();
104 if (exdest!=field_str_const_range_t{}) {
105 return libjmmcg::enum_tags::convert<ExDestination_t>(
reinterpret_cast<std::array<
char,
sizeof(ExDestination_t)>
const &>(*exdest.first));
107 return static_cast<ExDestination_t>(std::numeric_limits<std::underlying_type<ExDestination_t>::type>::max());
111 template<
class MsgVer>
inline MsgTypes
113 field_str_const_range_t
const &type_str=find<FieldsFast
::MsgType>();
114 if ((type_str.second-type_str.first)==1) {
115 const auto type_int=
static_cast<MsgTypes>(*type_str.first);
116 return static_cast<MsgTypes>(type_int);
122 conv.c[0]=type_str.first[0];
123 conv.c[1]=type_str.first[1];
124 return static_cast<MsgTypes>(conv.type_int);
128 template<
class MsgVer>
inline checksum_t
130 checksum_t fix_chk_sum{};
131 const std::size_t checksum=
std::accumulate(
this->begin_string,
std::next(
this->begin_string, body_len+1), 0UL);
132 const std::size_t checksum_mod=(checksum%256UL);
133 BOOST_MPL_ASSERT_RELATION(CheckSumLength, ==, 3);
134 [[maybe_unused]]
const int i=libjmmcg::tostring_zero_pad_right_justify<10, CheckSumLength>(checksum_mod,
reinterpret_cast<
char (&)[CheckSumLength]>(*fix_chk_sum.data()));
135 assert(i==CheckSumLength);
139 template<
class MsgVer>
constexpr inline bool
141 auto const &computed_chksum=generate_checksum(body_len+
sizeof(begin_string)+
sizeof(body_length_tag)+
sizeof(body_length_value));
142 return std::equal(computed_chksum.begin(), computed_chksum.end()-1, start_of_checksum_value);
145 template<
class MsgVer>
constexpr inline bool
147 const bool has_msg_ver=
std::equal(
this->begin_string,
this->body_length_tag, msg_version_t::MsgVer);
149 auto constexpr const &msg_str=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::BodyLength>::value;
150 const bool has_msg_size=std::equal(
this->body_length_tag,
this->body_length_value, msg_str);
152 const_pointer next_field=
this->body_length_value;
154 underlying_fix_data_buffer::const_iterator end_of_body_size=
this->msg_type_tag;
157 && (body_size<(max_size_of_fix_message-
sizeof(msg_version_t::MsgVer)-msg_version_t::fix_template_body_length_offset-
sizeof(
JMMCG_FIX_MSG_BODY_LENGTH_NULL)-1))
158 && ((end_of_body_size-
this->begin_string)>0)
160 auto const &checksum_str=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::value;
161 underlying_fix_data_buffer::const_iterator start_of_checksum=end_of_body_size+body_size;
162 const bool has_checksum=std::equal(start_of_checksum, start_of_checksum+libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size, checksum_str);
164 const bool has_terminal_separator=(*(end_of_body_size+body_size+libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size+CheckSumLength)==Separator);
165 if (has_terminal_separator) {
166 const_pointer start_of_checksum_value=end_of_body_size+body_size+libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size;
167 return is_checksum_valid(body_size, start_of_checksum_value);
179 using JMMCG_FIX_MSG_SEQ_NUM_TAG_t=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::element_type;
180 pointer data=
static_cast<pointer>(
begin_string)+MsgVer::fix_template_msg_type_offset;
181 libjmmcg::memcpy_opt(
182 libjmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::value,
183 reinterpret_cast<
typename libjmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::element_type &>(*data)
185 data+=libjmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::size;
186 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
187 assert(
static_cast<size_type>(data-start)<
this->length());
188 libjmmcg::memcpy_opt(
189 libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::value,
190 reinterpret_cast<JMMCG_FIX_MSG_SEQ_NUM_TAG_t &>(*data)
192 data+=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::size;
193 assert(
static_cast<size_type>(data-start)<
this->length());
200 pointer data=set_header<MsgType>();
201 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
202 assert(
static_cast<size_type>(data-start)<
this->length());
203 const int i=libjmmcg::tostring(
206 data_.size()-MsgVer::fix_template_msg_type_offset-libjmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::size-libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::size+1
210 assert(
static_cast<size_type>(data-start)<
this->length());
215 template<MsgTypes MsgType,
class SrcMsg,
class Ret>
inline constexpr Ret
217 return this->set_sequence_num_int<MsgType>(msg.sequenceNumber);
220 template<
class MsgVer>
constexpr inline __stdcall
225 template<
class MsgVer>
constexpr inline __stdcall
230 template<
class MsgVer>
constexpr inline __stdcall
235 template<
class MsgVer>
constexpr inline __stdcall
241 template<
class MsgVer>
constexpr inline typename Message<MsgVer>::size_type
__fastcall
243 const size_type body_size=libjmmcg::fromstring<size_type>(
this->body_length_value);
244 assert(body_size<
this->length());
249 template<FieldsFast field>
250 constexpr inline bool __fastcall
253 const_pointer
const start=
this->body_length_tag;
254 const_pointer field_ptr=
this->body_length_tag;
255 field_ptr=libjmmcg::strstr_opt(
reinterpret_cast<body_type &>(*field_ptr), libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value);
256 assert(field_ptr>=start);
257 return static_cast<size_type>(field_ptr-start)<=
this->length();
260 template<
class MsgVer>
constexpr inline bool
262 return Header_t::is_valid() && msg_version_t::is_valid(*
this);
265 template<
class MsgVer>
constexpr common::ClientOrderID_t
267 field_str_const_range_t
const &type_str=
this->
template find<FieldsFast
::ClOrdID>();
268 assert((type_str.second-type_str.first)>0);
269 common::ClientOrderID_t ret{};
270 assert(
static_cast<size_type>(type_str.second-type_str.first)<=ret.max_size());
271 std::copy(type_str.first, type_str.second, ret.begin());
275 template<
class MsgVer>
constexpr inline common::Side
277 field_str_const_range_t
const &type_str=
this->
template find<FieldsFast
::Side>();
278 assert((type_str.second-type_str.first)==1);
279 return static_cast<common::Side>(*type_str.first);
282 template<
class MsgVer>
constexpr inline Price_t
284 field_str_const_range_t
const &type_str=
this->
template find<FieldsFast
::Price>();
285 assert((type_str.second-type_str.first)>0);
286 const auto price=libjmmcg::fromstring<Price_t>(type_str.first, type_str.second-type_str.first);
287 return price*implied_decimal_places;
290 template<
class MsgVer>
constexpr inline Quantity_t
292 field_str_const_range_t
const &type_str=
this->
template find<FieldsFast
::OrderQty>();
293 assert((type_str.second-type_str.first)>0);
294 const auto qty=libjmmcg::fromstring<Quantity_t>(type_str.first, type_str.second-type_str.first-1);
298 template<
class MsgVer>
constexpr inline void
300 field_str_range_t type_str=
this->
template find<FieldsFast::OrderQty>();
301 assert((type_str.second-type_str.first)>0);
302 [[maybe_unused]]
auto const i=libjmmcg::tostring(q, type_str.first, type_str.second-type_str.first);
306 template<
class MsgVer>
constexpr inline SecurityID_t
308 field_str_const_range_t
const &type_str=
this->
template find<FieldsFast
::SecurityID>();
309 assert((type_str.second-type_str.first)>0);
311 assert(
static_cast<size_type>(type_str.second-type_str.first)<=ret.max_size());
312 std::copy(type_str.first, type_str.second, ret.begin());
317 template<
class OutIter>
320 data=add_field_tag<FieldsFast
::ClOrdID>(data);
321 libjmmcg::memcpy_opt(clID,
reinterpret_cast<ClientOrderID_t &>(*data));
323 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
324 assert(
static_cast<size_type>(data-start)<
this->data_.size());
329 template<
class OutIter>
inline OutIter
332 boost::posix_time::ptime
const timeUTC=boost::posix_time::microsec_clock::universal_time();
333 auto const &as_ISO_str=
boost::posix_time::to_iso_extended_string(timeUTC);
334 auto const end=
std::copy(as_ISO_str.begin(), as_ISO_str.end(), data);
336 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
337 assert(
static_cast<size_type>(end-start)<
this->data_.size());
342 template<
class OutIter>
inline OutIter
345 *data=
static_cast<std::underlying_type<ExDestinationIDSource>::type>(ExDestinationIDSource
::MIC);
347 [[maybe_unused]] const_pointer
const start=
this->body_length_tag;
348 assert(
static_cast<size_type>(data-start)<
this->data_.size());
350 assert(
static_cast<size_type>(data-start)<
this->data_.size());
351 libjmmcg::memcpy_opt(
352 reinterpret_cast<
std::array<
char,
sizeof(ExDestination_t)>
const &>(mic),
353 reinterpret_cast<
std::array<
char,
sizeof(ExDestination_t)> &>(*data)
355 data+=
sizeof(ExDestination_t);
356 assert(
static_cast<size_type>(data-start)<
this->data_.size());
361 template<FieldsFast field>
364 [[maybe_unused]] const_pointer
const start=
this->body_length_value+
sizeof(
this->body_length_value);
365 assert(
static_cast<size_type>(data-start)<(
this->data_.size()));
366 libjmmcg::memcpy_opt(
367 libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value,
368 reinterpret_cast<
typename libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::element_type &>(*data)
370 data+=libjmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
371 assert(
static_cast<size_type>(data-start)<(
this->data_.size()));
375 template<
class MsgVer>
inline std::string
377 std::stringstream ss;
380 <<
this->body_length_tag
381 <<
this->body_length_value
387 template<
class MsgVer>
constexpr inline void
395 assert(i>0 &&
static_cast<size_type>(i)<
sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL));
396 underlying_fix_data_buffer::iterator ptr=data;
397 using JMMCG_FIX_MSG_CHECKSUM_TAG_t=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::element_type;
398 libjmmcg::memcpy_opt(libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::value,
reinterpret_cast<JMMCG_FIX_MSG_CHECKSUM_TAG_t &>(*ptr));
399 ptr+=libjmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size;
400 checksum_t
const &checksum=
this->generate_checksum(data-
this->begin_string);
401 libjmmcg::memcpy_opt(checksum,
reinterpret_cast<checksum_t &>(*ptr));
404 assert(
this->is_valid());
405 assert((ptr-
this->begin_string)>0);
406 assert(
static_cast<size_type>(ptr-
this->begin_string)<
this->data_.size());
407 assert(
this->is_valid());
410 template<
class MsgVer>
inline std::ostream &
411 operator<<(
std::ostream &os,
Message<MsgVer>
const &m) {