29 #include <type_traits>
31 #include <string_view>
33 #include "core/compiler/hints_branch_predictor.h"
34 #include "core/compiler/unused.h"
36 #include "core/os/assert_msg.h"
38 #include "core/utilities/converters.h"
39 #include "core/utilities/dictionary.h"
41 #include "electronic_trading/common/fixed_point.h"
43 #include "fix_constants.h"
44 #include "fix_string_view.h"
45 #include "incoming_fix_repeating_groups.h"
52 FixStringView* value =
nullptr;
53 uint64_t generation_id = 0;
76 return m_dict.initialise(64);
87 if (m_dict.has_key(tag) ==
false)
92 return m_dict[tag].generation_id == m_generation_id;
95 void set_tag(uint32_t tag, FixStringView* value)
99 node.generation_id = m_generation_id;
101 if (llfix_likely(m_dict.has_key(tag)))
103 m_dict.set_existing_item(tag, node);
107 m_dict.insert(tag, node);
111 void copy_non_dirty_tag_values_from(
const IncomingFixMessage& other)
113 for (
const auto& item : other.m_dict)
115 if(other.has_tag(item.key))
117 set_tag(item.key, item.value.value);
121 m_repeating_groups.copy_non_dirty_values_from(other.m_repeating_groups);
124 IncomingFixRepeatingGroups<FixStringView>& get_repeating_groups()
126 return m_repeating_groups;
129 void set_repeating_group_tag(uint32_t tag, FixStringView* value)
131 m_repeating_groups.set(tag, value);
143 return m_repeating_groups.has_tag(tag);
150 if(m_generation_id == 0)
153 for (
auto& it : m_dict)
155 it.value.generation_id = 0;
162 m_repeating_groups.reset();
183 auto is_header_tag = [](uint32_t tag)
185 if (tag == FixConstants::TAG_BEGIN_STRING || tag == FixConstants::TAG_BODY_LENGTH || tag == FixConstants::TAG_MSG_TYPE || tag == FixConstants::TAG_MSG_SEQ_NUM || tag == FixConstants::TAG_SENDING_TIME || tag == FixConstants::TAG_SENDER_COMP_ID || tag == FixConstants::TAG_TARGET_COMP_ID)
190 auto is_trailer_tag = [](uint32_t tag)
192 if (tag == FixConstants::TAG_CHECKSUM)
200 if(
has_tag(FixConstants::TAG_BEGIN_STRING)) ret +=
"8=" + get_tag_value_as<std::string>(FixConstants::TAG_BEGIN_STRING) +
'|';
201 if (
has_tag(FixConstants::TAG_BODY_LENGTH)) ret +=
"9=" + get_tag_value_as<std::string>(FixConstants::TAG_BODY_LENGTH) +
'|';
202 if (
has_tag(FixConstants::TAG_MSG_TYPE)) ret +=
"35=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_TYPE) +
'|';
203 if (
has_tag(FixConstants::TAG_MSG_SEQ_NUM)) ret +=
"34=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_SEQ_NUM) +
'|';
204 if (
has_tag(FixConstants::TAG_SENDER_COMP_ID)) ret +=
"49=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDER_COMP_ID) +
'|';
205 if (
has_tag(FixConstants::TAG_SENDING_TIME)) ret +=
"52=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDING_TIME) +
'|';
206 if (
has_tag(FixConstants::TAG_TARGET_COMP_ID)) ret +=
"56=" + get_tag_value_as<std::string>(FixConstants::TAG_TARGET_COMP_ID) +
'|';
209 for (
const auto& item : m_dict)
211 if (item.value.generation_id == m_generation_id)
213 if (is_header_tag(item.key) ==
false && is_trailer_tag(item.key) ==
false)
215 ret += std::to_string(item.key) +
'=' + item.value.value->to_string() +
'|';
221 ret += m_repeating_groups.to_string();
224 if (
has_tag(FixConstants::TAG_CHECKSUM)) ret +=
"10=" + get_tag_value_as<std::string>(FixConstants::TAG_CHECKSUM) +
'|';
228 return "An error occured during IncomingFixMessage::to_string call";
235 FixStringView* get_tag_value(uint32_t tag)
const
237 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
238 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
239 return m_dict[tag].value;
263 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
264 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
266 if constexpr (std::is_same_v<T, std::string>)
268 LLFIX_UNUSED(decimal_points);
269 return m_dict[tag].value->to_string();
272 else if constexpr (std::is_same_v<T, char>)
274 LLFIX_UNUSED(decimal_points);
275 return m_dict[tag].value->data()[0];
277 else if constexpr (std::is_same_v<T, std::string_view>)
279 LLFIX_UNUSED(decimal_points);
280 return m_dict[tag].value->to_string_view();
282 else if constexpr (std::is_same_v<T, bool>)
284 LLFIX_UNUSED(decimal_points);
285 return (m_dict[tag].value->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
287 else if constexpr (std::is_same_v<T, FixedPoint>)
289 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
292 fp.
set_from_chars(m_dict[tag].value->c_str(), m_dict[tag].value->length());
295 else if constexpr (std::is_floating_point<T>::value)
297 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
298 return static_cast<T
>(Converters::chars_to_double(m_dict[tag].value->c_str(), m_dict[tag].value->length(), decimal_points));
300 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
302 LLFIX_UNUSED(decimal_points);
303 return Converters::chars_to_int<int>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
305 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
307 LLFIX_UNUSED(decimal_points);
308 return Converters::chars_to_unsigned_int<uint64_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
310 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
312 LLFIX_UNUSED(decimal_points);
313 return Converters::chars_to_unsigned_int<uint32_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
317 static_assert(always_false_v<T>,
"get_tag_value_as unsupported type");
343 FixStringView* str_val = m_repeating_groups.get_value(tag, index);
344 llfix_assert_msg(str_val !=
nullptr,
"You should call has_repeating_group_tag first");
346 if constexpr (std::is_same_v<T, std::string>)
348 LLFIX_UNUSED(decimal_points);
349 return str_val->to_string();
351 else if constexpr (std::is_same_v<T, char>)
353 LLFIX_UNUSED(decimal_points);
354 return str_val->data()[0];
356 else if constexpr (std::is_same_v<T, std::string_view>)
358 LLFIX_UNUSED(decimal_points);
359 return str_val->to_string_view();
361 else if constexpr (std::is_same_v<T, bool>)
363 LLFIX_UNUSED(decimal_points);
364 return (str_val->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
366 else if constexpr (std::is_same_v<T, FixedPoint>)
368 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
374 else if constexpr (std::is_floating_point<T>::value)
376 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
377 return Converters::chars_to_double(str_val->c_str(), str_val->length(), decimal_points);
379 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
381 LLFIX_UNUSED(decimal_points);
382 return Converters::chars_to_int<int>(str_val->c_str(), str_val->length());
384 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
386 LLFIX_UNUSED(decimal_points);
387 return Converters::chars_to_unsigned_int<uint64_t>(str_val->c_str(), str_val->length());
389 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
391 LLFIX_UNUSED(decimal_points);
392 return Converters::chars_to_unsigned_int<uint32_t>(str_val->c_str(), str_val->length());
396 static_assert(always_false_v<T>,
"get_repeating_group_tag_value_as unsupported type");
401 bool is_tag_value_numeric(uint32_t tag)
const
403 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
404 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
405 return m_dict[tag].value->is_numeric();
408 bool validate_count_tag(uint32_t tag, uint32_t& out_reject_message_code)
const
410 return m_repeating_groups.validate_count_tag(tag, out_reject_message_code);
413 Dictionary<uint32_t, IncomingValue>* get_dictionary()
420 uint64_t get_generation_id()
const {
return m_generation_id; }
426 const_iterator(Dictionary<uint32_t, IncomingValue>::iterator current, Dictionary<uint32_t, IncomingValue>::iterator end, uint64_t generation_id)
427 : m_current(current), m_end(end), m_generation_id(generation_id)
429 skip_stale_entries();
432 const Dictionary<uint32_t, IncomingValue>::DictionaryNode& operator*()
const
437 const_iterator& operator++()
440 skip_stale_entries();
444 friend bool operator==(
const const_iterator& a,
const const_iterator& b)
446 return a.m_current == b.m_current;
449 friend bool operator!=(
const const_iterator& a,
const const_iterator& b)
451 return a.m_current != b.m_current;
455 void skip_stale_entries()
457 while (m_current != m_end && m_current->value.generation_id != m_generation_id)
463 Dictionary<uint32_t, IncomingValue>::iterator m_current;
464 Dictionary<uint32_t, IncomingValue>::iterator m_end;
465 uint64_t m_generation_id = 0;
468 const_iterator begin()
const
470 return const_iterator(m_dict.begin(), m_dict.end(), m_generation_id);
473 const_iterator end()
const
475 return const_iterator(m_dict.end(), m_dict.end(), m_generation_id);
479 uint64_t m_generation_id = 1;
480 mutable Dictionary<uint32_t, IncomingValue> m_dict;
481 IncomingFixRepeatingGroups<FixStringView> m_repeating_groups;
484 static constexpr
bool always_false_v =
false;
486 IncomingFixMessage(
const IncomingFixMessage& other) =
delete;
487 IncomingFixMessage& operator= (
const IncomingFixMessage& other) =
delete;
488 IncomingFixMessage(IncomingFixMessage&& other) =
delete;
489 IncomingFixMessage& operator=(IncomingFixMessage&& other) =
delete;