10 #include "core/compiler/hints_branch_predictor.h"
11 #include "core/compiler/unused.h"
13 #include "core/os/assert_msg.h"
15 #include "core/utilities/converters.h"
16 #include "core/utilities/dictionary.h"
18 #include "electronic_trading/common/fixed_point.h"
20 #include "fix_constants.h"
21 #include "fix_string_view.h"
22 #include "incoming_fix_repeating_groups.h"
29 FixStringView* value =
nullptr;
30 uint64_t generation_id = 0;
53 return m_dict.initialise(64);
64 if (m_dict.has_key(tag) ==
false)
69 return m_dict[tag].generation_id == m_generation_id;
72 void set_tag(uint32_t tag, FixStringView* value)
76 node.generation_id = m_generation_id;
78 if (llfix_likely(m_dict.has_key(tag)))
80 m_dict.set_existing_item(tag, node);
84 m_dict.insert(tag, node);
88 void copy_non_dirty_tag_values_from(
const IncomingFixMessage& other)
90 for (
const auto& item : other.m_dict)
92 if(other.has_tag(item.key))
94 set_tag(item.key, item.value.value);
98 m_repeating_groups.copy_non_dirty_values_from(other.m_repeating_groups);
101 IncomingFixRepeatingGroups<FixStringView>& get_repeating_groups()
103 return m_repeating_groups;
106 void set_repeating_group_tag(uint32_t tag, FixStringView* value)
108 m_repeating_groups.set(tag, value);
120 return m_repeating_groups.has_tag(tag);
127 if(m_generation_id == 0)
130 for (
auto& it : m_dict)
132 it.value.generation_id = 0;
139 m_repeating_groups.reset();
160 auto is_header_tag = [](uint32_t tag)
162 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)
167 auto is_trailer_tag = [](uint32_t tag)
169 if (tag == FixConstants::TAG_CHECKSUM)
177 if(
has_tag(FixConstants::TAG_BEGIN_STRING)) ret +=
"8=" + get_tag_value_as<std::string>(FixConstants::TAG_BEGIN_STRING) +
'|';
178 if (
has_tag(FixConstants::TAG_BODY_LENGTH)) ret +=
"9=" + get_tag_value_as<std::string>(FixConstants::TAG_BODY_LENGTH) +
'|';
179 if (
has_tag(FixConstants::TAG_MSG_TYPE)) ret +=
"35=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_TYPE) +
'|';
180 if (
has_tag(FixConstants::TAG_MSG_SEQ_NUM)) ret +=
"34=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_SEQ_NUM) +
'|';
181 if (
has_tag(FixConstants::TAG_SENDER_COMP_ID)) ret +=
"49=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDER_COMP_ID) +
'|';
182 if (
has_tag(FixConstants::TAG_SENDING_TIME)) ret +=
"52=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDING_TIME) +
'|';
183 if (
has_tag(FixConstants::TAG_TARGET_COMP_ID)) ret +=
"56=" + get_tag_value_as<std::string>(FixConstants::TAG_TARGET_COMP_ID) +
'|';
186 for (
const auto& item : m_dict)
188 if (item.value.generation_id == m_generation_id)
190 if (is_header_tag(item.key) ==
false && is_trailer_tag(item.key) ==
false)
192 ret += std::to_string(item.key) +
'=' + item.value.value->to_string() +
'|';
198 ret += m_repeating_groups.to_string();
201 if (
has_tag(FixConstants::TAG_CHECKSUM)) ret +=
"10=" + get_tag_value_as<std::string>(FixConstants::TAG_CHECKSUM) +
'|';
205 return "An error occured during IncomingFixMessage::to_string call";
212 FixStringView* get_tag_value(uint32_t tag)
const
214 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
215 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
216 return m_dict[tag].value;
240 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
241 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
243 if constexpr (std::is_same_v<T, std::string>)
245 LLFIX_UNUSED(decimal_points);
246 return m_dict[tag].value->to_string();
249 else if constexpr (std::is_same_v<T, char>)
251 LLFIX_UNUSED(decimal_points);
252 return m_dict[tag].value->data()[0];
254 else if constexpr (std::is_same_v<T, std::string_view>)
256 LLFIX_UNUSED(decimal_points);
257 return m_dict[tag].value->to_string_view();
259 else if constexpr (std::is_same_v<T, bool>)
261 LLFIX_UNUSED(decimal_points);
262 return (m_dict[tag].value->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
264 else if constexpr (std::is_same_v<T, FixedPoint>)
266 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
269 fp.
set_from_chars(m_dict[tag].value->c_str(), m_dict[tag].value->length());
272 else if constexpr (std::is_floating_point<T>::value)
274 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
275 return static_cast<T
>(Converters::chars_to_double(m_dict[tag].value->c_str(), m_dict[tag].value->length(), decimal_points));
277 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
279 LLFIX_UNUSED(decimal_points);
280 return Converters::chars_to_int<int>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
282 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
284 LLFIX_UNUSED(decimal_points);
285 return Converters::chars_to_unsigned_int<uint64_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
287 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
289 LLFIX_UNUSED(decimal_points);
290 return Converters::chars_to_unsigned_int<uint32_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
294 static_assert(always_false_v<T>,
"get_tag_value_as unsupported type");
320 FixStringView* str_val = m_repeating_groups.get_value(tag, index);
321 llfix_assert_msg(str_val !=
nullptr,
"You should call has_repeating_group_tag first");
323 if constexpr (std::is_same_v<T, std::string>)
325 LLFIX_UNUSED(decimal_points);
326 return str_val->to_string();
328 else if constexpr (std::is_same_v<T, char>)
330 LLFIX_UNUSED(decimal_points);
331 return str_val->data()[0];
333 else if constexpr (std::is_same_v<T, std::string_view>)
335 LLFIX_UNUSED(decimal_points);
336 return str_val->to_string_view();
338 else if constexpr (std::is_same_v<T, bool>)
340 LLFIX_UNUSED(decimal_points);
341 return (str_val->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
343 else if constexpr (std::is_same_v<T, FixedPoint>)
345 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
351 else if constexpr (std::is_floating_point<T>::value)
353 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
354 return Converters::chars_to_double(str_val->c_str(), str_val->length(), decimal_points);
356 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
358 LLFIX_UNUSED(decimal_points);
359 return Converters::chars_to_int<int>(str_val->c_str(), str_val->length());
361 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
363 LLFIX_UNUSED(decimal_points);
364 return Converters::chars_to_unsigned_int<uint64_t>(str_val->c_str(), str_val->length());
366 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
368 LLFIX_UNUSED(decimal_points);
369 return Converters::chars_to_unsigned_int<uint32_t>(str_val->c_str(), str_val->length());
373 static_assert(always_false_v<T>,
"get_repeating_group_tag_value_as unsupported type");
378 bool is_tag_value_numeric(uint32_t tag)
const
380 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
381 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
382 return m_dict[tag].value->is_numeric();
385 bool validate_count_tag(uint32_t tag, uint32_t& out_reject_message_code)
const
387 return m_repeating_groups.validate_count_tag(tag, out_reject_message_code);
390 Dictionary<uint32_t, IncomingValue>* get_dictionary()
395 uint64_t get_generation_id()
const {
return m_generation_id; }
398 uint64_t m_generation_id = 1;
399 mutable Dictionary<uint32_t, IncomingValue> m_dict;
400 IncomingFixRepeatingGroups<FixStringView> m_repeating_groups;
403 static constexpr
bool always_false_v =
false;
405 IncomingFixMessage(
const IncomingFixMessage& other) =
delete;
406 IncomingFixMessage& operator= (
const IncomingFixMessage& other) =
delete;
407 IncomingFixMessage(IncomingFixMessage&& other) =
delete;
408 IncomingFixMessage& operator=(IncomingFixMessage&& other) =
delete;