This source file includes following definitions.
- length
- find
- find
- type
- set_header
- set_sequence_num
- size
- search
- generate_checksum
- is_checksum_valid
- is_valid
- add_field_tag
- to_string
- finalise_msg
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 namespace isimud { namespace exchanges { namespace FIX { namespace common {
22
23 template<class MsgVer> inline constexpr __stdcall
24 Header<MsgVer>::Header() noexcept(true) {
25 using fix_template_to_msg_type_t=underlying_fix_data_buffer::value_type[MsgVer::fix_template_msg_type_offset];
26 jmmcg::memcpy_opt(
27 MsgVer::fix_template_to_msg_type,
28 reinterpret_cast<fix_template_to_msg_type_t &>(*begin_string)
29 );
30 }
31
32 template<class MsgVer> inline constexpr typename Header<MsgVer>::size_type
33 Header<MsgVer>::length() const noexcept(true) {
34 const size_type body_size=jmmcg::fromstring<size_type>(body_length_value, sizeof(body_length_value));
35 return msg_type_tag-begin_string+body_size+jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size+CheckSumLength+sizeof(Separator);
36 }
37
38 template<class MsgVer>
39 template<FieldsFast field> inline
40 constexpr field_str_range_t __fastcall
41 Header<MsgVer>::find() noexcept(true) {
42 using body_type=char const [max_size_of_fix_message];
43 [[maybe_unused]] const_pointer const start=this->body_length_tag;
44 const_pointer field_ptr=this->body_length_tag;
45 const constexpr std::size_t field_len=jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
46 field_ptr=jmmcg::strstr_opt(reinterpret_cast<body_type &>(*field_ptr), jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value);
47 assert(field_ptr);
48 field_ptr+=field_len;
49 const_pointer end=field_ptr;
50 end=jmmcg::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>(field_ptr-start)<this->length());
54 assert(static_cast<size_type>(end-start)<this->length());
55 return field_str_range_t(field_ptr, end-1);
56 }
57
58 template<class MsgVer>
59 template<FieldsFast field> inline
60 constexpr field_str_range_t const __fastcall
61 Header<MsgVer>::find() const noexcept(true) {
62 using body_type=char const [max_size_of_fix_message];
63 [[maybe_unused]] const_pointer const start=this->body_length_tag;
64 const_pointer field_ptr=this->body_length_tag;
65 const constexpr std::size_t field_len=jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
66 field_ptr=jmmcg::strstr_opt(reinterpret_cast<body_type &>(*field_ptr), jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value);
67 assert(field_ptr);
68 field_ptr+=field_len;
69 const_pointer end=field_ptr;
70 end=jmmcg::strchr_opt<Separator>(reinterpret_cast<body_type &>(*end))+1;
71 assert((end-field_ptr)>0);
72 assert(static_cast<size_type>(end-field_ptr)<this->length());
73 assert(static_cast<size_type>(field_ptr-start)<this->length());
74 assert(static_cast<size_type>(end-start)<this->length());
75 return field_str_range_t(field_ptr, end-1);
76 }
77
78 template<class MsgVer> inline MsgTypes
79 Header<MsgVer>::type() const noexcept(true) {
80 field_str_range_t const &type_str=find<FieldsFast::MsgType>();
81 if ((type_str.second-type_str.first)==1) {
82 const auto type_int=static_cast<MsgTypes>(*type_str.first);
83 return static_cast<MsgTypes>(type_int);
84 } else {
85 union {
86 char c[2];
87 MsgTypes_t type_int;
88 } conv;
89 conv.c[0]=type_str.first[0];
90 conv.c[1]=type_str.first[1];
91 return static_cast<MsgTypes>(conv.type_int);
92 }
93 }
94
95 template<class MsgVer>
96 template<MsgTypes MsgType> inline constexpr underlying_fix_data_buffer::iterator
97 Header<MsgVer>::set_header() noexcept(true) {
98 using JMMCG_FIX_MSG_SEQ_NUM_TAG_t=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::element_type;
99 pointer data=begin_string+MsgVer::fix_template_msg_type_offset;
100 jmmcg::memcpy_opt(
101 jmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::value,
102 reinterpret_cast<typename jmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::element_type &>(*data)
103 );
104 data+=jmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::size;
105 jmmcg::memcpy_opt(
106 jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::value,
107 reinterpret_cast<JMMCG_FIX_MSG_SEQ_NUM_TAG_t &>(*data)
108 );
109 data+=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::size;
110 return data;
111 }
112
113 template<class MsgVer>
114 template<MsgTypes MsgType, class SrcMsg> inline constexpr underlying_fix_data_buffer::iterator
115 Header<MsgVer>::set_sequence_num(SrcMsg const &msg) noexcept(true) {
116 pointer data=set_header<MsgType>();
117 const int i=jmmcg::tostring(
118 msg.sequenceNumber,
119 data,
120 data_.size()-MsgVer::fix_template_msg_type_offset-jmmcg::enum_tags::mpl::to_array<MsgTypes, MsgType>::size-jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::MsgSeqNum>::size+1
121 );
122 assert(i>0);
123 data+=i;
124 return data;
125 }
126
127 template<class MsgVer> constexpr inline __stdcall
128 Message<MsgVer>::Message() noexcept(true)
129 : Header_t() {
130 }
131
132 template<class MsgVer> constexpr inline __stdcall
133 Message<MsgVer>::Message(logon_args_t const &) noexcept(true)
134 : Header_t() {
135 }
136
137 template<class MsgVer> constexpr inline __stdcall
138 Message<MsgVer>::Message(logoff_args_t const &) noexcept(true)
139 : Header_t() {
140 }
141
142 template<class MsgVer> constexpr inline __stdcall
143 Message<MsgVer>::Message(RejectCode_t const &) noexcept(true)
144 : Header_t() {
145
146 }
147
148 template<class MsgVer> constexpr inline typename Message<MsgVer>::size_type __fastcall
149 Message<MsgVer>::size() const noexcept(true) {
150 const size_type body_size=jmmcg::fromstring<size_type>(this->body_length_value);
151 assert(body_size<this->length());
152 return body_size;
153 }
154
155 template<class MsgVer>
156 template<FieldsFast field>
157 constexpr inline bool __fastcall
158 Message<MsgVer>::search() const noexcept(true) {
159 using body_type=char const [max_size_of_fix_message];
160 const_pointer const start=this->body_length_tag;
161 const_pointer field_ptr=this->body_length_tag;
162 field_ptr=jmmcg::strstr_opt(reinterpret_cast<body_type &>(*field_ptr), jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value);
163 assert(field_ptr>=start);
164 return static_cast<size_type>(field_ptr-start)<=this->length();
165 }
166
167 template<class MsgVer> inline checksum_t
168 Message<MsgVer>::generate_checksum(size_type body_len) const noexcept(true) {
169 checksum_t fix_chk_sum{};
170 const std::size_t checksum=std::accumulate(this->begin_string, std::next(this->begin_string, body_len+(this->body_length_value-this->begin_string)), 0UL);
171 const std::size_t checksum_mod=(checksum%256UL);
172 BOOST_MPL_ASSERT_RELATION(CheckSumLength, ==, 3);
173 [[maybe_unused]] const int i=jmmcg::tostring_zero_pad_right_justify<10, CheckSumLength>(checksum_mod, reinterpret_cast<char (&)[CheckSumLength]>(*fix_chk_sum.data()));
174 assert(i==CheckSumLength);
175 return fix_chk_sum;
176 }
177
178 template<class MsgVer> constexpr inline bool
179 Message<MsgVer>::is_checksum_valid(size_type body_len, const_pointer start_of_checksum_value) const noexcept(true) {
180 auto const &computed_chksum=generate_checksum(body_len);
181 return std::equal(computed_chksum.begin(), computed_chksum.end()-1, start_of_checksum_value);
182 }
183
184 template<class MsgVer> constexpr inline bool
185 Message<MsgVer>::is_valid() const noexcept(true) {
186 const bool has_msg_ver=std::equal(this->begin_string, this->body_length_tag, msg_version_t::MsgVer);
187 if (has_msg_ver) {
188 auto const &msg_str=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::BodyLength>::value;
189 const bool has_msg_size=std::equal(this->body_length_tag, this->body_length_value, msg_str);
190 if (has_msg_size) {
191 const_pointer next_field=this->body_length_value;
192 const size_type body_size=jmmcg::fromstring<size_type>(next_field, sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)-1);
193 underlying_fix_data_buffer::const_iterator end_of_body_size=this->msg_type_tag;
194 if (
195 body_size>0
196 && (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))
197 && ((end_of_body_size-this->begin_string)>0)
198 ) {
199 auto const &checksum_str=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::value;
200 underlying_fix_data_buffer::const_iterator start_of_checksum=end_of_body_size+body_size;
201 const bool has_checksum=std::equal(start_of_checksum, start_of_checksum+jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size, checksum_str);
202 if (has_checksum) {
203 const bool has_terminal_separator=(*(end_of_body_size+body_size+jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size+CheckSumLength)==Separator);
204 if (has_terminal_separator) {
205 const_pointer start_of_checksum_value=end_of_body_size+body_size+jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size;
206 return is_checksum_valid(body_size, start_of_checksum_value) && msg_version_t::is_valid(*this);
207 }
208 }
209 }
210 }
211 }
212 return false;
213 }
214
215 template<class MsgVer>
216 template<FieldsFast field>
217 constexpr inline underlying_fix_data_buffer::iterator
218 Message<MsgVer>::add_field_tag(underlying_fix_data_buffer::iterator data) noexcept(true) {
219 jmmcg::memcpy_opt(
220 jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::value,
221 reinterpret_cast<typename jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::element_type &>(*data)
222 );
223 return data+jmmcg::enum_tags::mpl::to_array<FieldsFast, field>::size;
224 }
225
226 template<class MsgVer> inline std::string
227 Message<MsgVer>::to_string() const noexcept(false) {
228 std::stringstream ss;
229 ss
230 <<this->begin_string
231 <<this->body_length_tag
232 <<this->body_length_value
233 <<this->msg_type_tag
234 <<this->data_;
235 return ss.str();
236 }
237
238 template<class MsgVer> constexpr inline void
239 Message<MsgVer>::finalise_msg(underlying_fix_data_buffer::iterator data) noexcept(true) {
240 const std::size_t length=data-this->begin_string-MsgVer::fix_template_body_length_offset-sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)+1;
241 BOOST_MPL_ASSERT_RELATION(sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)-1, ==, 3);
242 [[maybe_unused]] const int i=jmmcg::tostring_zero_pad_right_justify<10, sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)-1>(
243 length,
244 reinterpret_cast<char (&)[sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL)-1]>(*(this->body_length_value))
245 );
246 assert(i>0 && static_cast<std::size_t>(i)<sizeof(JMMCG_FIX_MSG_BODY_LENGTH_NULL));
247 underlying_fix_data_buffer::iterator ptr=data;
248 using JMMCG_FIX_MSG_CHECKSUM_TAG_t=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::element_type;
249 jmmcg::memcpy_opt(jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::value, reinterpret_cast<JMMCG_FIX_MSG_CHECKSUM_TAG_t &>(*ptr));
250 ptr+=jmmcg::enum_tags::mpl::to_array<FieldsFast, FieldsFast::CheckSum>::size;
251 checksum_t const &checksum=generate_checksum(length);
252 jmmcg::memcpy_opt(checksum, reinterpret_cast<checksum_t &>(*ptr));
253 ptr+=CheckSumLength;
254 *ptr=Separator;
255 assert(this->is_valid());
256 assert((ptr-this->begin_string)>0);
257 assert(static_cast<size_type>(ptr-this->begin_string)<this->data_.size());
258 }
259
260 template<class MsgVer> inline std::ostream &
261 operator<<(std::ostream &os, Message<MsgVer> const &m) {
262 os<<m.to_string();
263 return os;
264 }
265
266 } } } }