28 #include <type_traits>
30 #include <string_view>
32 #include "core/compiler/hints_branch_predictor.h"
33 #include "core/compiler/unused.h"
35 #include "core/os/assert_msg.h"
37 #include "core/utilities/converters.h"
38 #include "core/utilities/dictionary.h"
40 #include "electronic_trading/common/fixed_point.h"
42 #include "fix_constants.h"
43 #include "fix_string_view.h"
44 #include "incoming_fix_repeating_groups.h"
51 FixStringView* value =
nullptr;
52 uint64_t generation_id = 0;
75 return m_dict.initialise(64);
86 if (m_dict.has_key(tag) ==
false)
91 return m_dict[tag].generation_id == m_generation_id;
94 void set_tag(uint32_t tag, FixStringView* value)
98 node.generation_id = m_generation_id;
100 if (llfix_likely(m_dict.has_key(tag)))
102 m_dict.set_existing_item(tag, node);
106 m_dict.insert(tag, node);
110 void copy_non_dirty_tag_values_from(
const IncomingFixMessage& other)
112 for (
const auto& item : other.m_dict)
114 if(other.has_tag(item.key))
116 set_tag(item.key, item.value.value);
120 m_repeating_groups.copy_non_dirty_values_from(other.m_repeating_groups);
123 IncomingFixRepeatingGroups<FixStringView>& get_repeating_groups()
125 return m_repeating_groups;
128 void set_repeating_group_tag(uint32_t tag, FixStringView* value)
130 m_repeating_groups.set(tag, value);
142 return m_repeating_groups.has_tag(tag);
149 if(m_generation_id == 0)
152 for (
auto& it : m_dict)
154 it.value.generation_id = 0;
161 m_repeating_groups.reset();
182 auto is_header_tag = [](uint32_t tag)
184 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)
189 auto is_trailer_tag = [](uint32_t tag)
191 if (tag == FixConstants::TAG_CHECKSUM)
199 if(
has_tag(FixConstants::TAG_BEGIN_STRING)) ret +=
"8=" + get_tag_value_as<std::string>(FixConstants::TAG_BEGIN_STRING) +
'|';
200 if (
has_tag(FixConstants::TAG_BODY_LENGTH)) ret +=
"9=" + get_tag_value_as<std::string>(FixConstants::TAG_BODY_LENGTH) +
'|';
201 if (
has_tag(FixConstants::TAG_MSG_TYPE)) ret +=
"35=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_TYPE) +
'|';
202 if (
has_tag(FixConstants::TAG_MSG_SEQ_NUM)) ret +=
"34=" + get_tag_value_as<std::string>(FixConstants::TAG_MSG_SEQ_NUM) +
'|';
203 if (
has_tag(FixConstants::TAG_SENDER_COMP_ID)) ret +=
"49=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDER_COMP_ID) +
'|';
204 if (
has_tag(FixConstants::TAG_SENDING_TIME)) ret +=
"52=" + get_tag_value_as<std::string>(FixConstants::TAG_SENDING_TIME) +
'|';
205 if (
has_tag(FixConstants::TAG_TARGET_COMP_ID)) ret +=
"56=" + get_tag_value_as<std::string>(FixConstants::TAG_TARGET_COMP_ID) +
'|';
208 for (
const auto& item : m_dict)
210 if (item.value.generation_id == m_generation_id)
212 if (is_header_tag(item.key) ==
false && is_trailer_tag(item.key) ==
false)
214 ret += std::to_string(item.key) +
'=' + item.value.value->to_string() +
'|';
220 ret += m_repeating_groups.to_string();
223 if (
has_tag(FixConstants::TAG_CHECKSUM)) ret +=
"10=" + get_tag_value_as<std::string>(FixConstants::TAG_CHECKSUM) +
'|';
227 return "An error occured during IncomingFixMessage::to_string call";
234 FixStringView* get_tag_value(uint32_t tag)
const
236 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
237 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
238 return m_dict[tag].value;
262 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
263 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
265 if constexpr (std::is_same_v<T, std::string>)
267 LLFIX_UNUSED(decimal_points);
268 return m_dict[tag].value->to_string();
271 else if constexpr (std::is_same_v<T, char>)
273 LLFIX_UNUSED(decimal_points);
274 return m_dict[tag].value->data()[0];
276 else if constexpr (std::is_same_v<T, std::string_view>)
278 LLFIX_UNUSED(decimal_points);
279 return m_dict[tag].value->to_string_view();
281 else if constexpr (std::is_same_v<T, bool>)
283 LLFIX_UNUSED(decimal_points);
284 return (m_dict[tag].value->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
286 else if constexpr (std::is_same_v<T, FixedPoint>)
288 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
291 fp.
set_from_chars(m_dict[tag].value->c_str(), m_dict[tag].value->length());
294 else if constexpr (std::is_floating_point<T>::value)
296 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
297 return static_cast<T
>(Converters::chars_to_double(m_dict[tag].value->c_str(), m_dict[tag].value->length(), decimal_points));
299 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
301 LLFIX_UNUSED(decimal_points);
302 return Converters::chars_to_int<int>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
304 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
306 LLFIX_UNUSED(decimal_points);
307 return Converters::chars_to_unsigned_int<uint64_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
309 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
311 LLFIX_UNUSED(decimal_points);
312 return Converters::chars_to_unsigned_int<uint32_t>(m_dict[tag].value->c_str(), m_dict[tag].value->length());
316 static_assert(always_false_v<T>,
"get_tag_value_as unsupported type");
342 FixStringView* str_val = m_repeating_groups.get_value(tag, index);
343 llfix_assert_msg(str_val !=
nullptr,
"You should call has_repeating_group_tag first");
345 if constexpr (std::is_same_v<T, std::string>)
347 LLFIX_UNUSED(decimal_points);
348 return str_val->to_string();
350 else if constexpr (std::is_same_v<T, char>)
352 LLFIX_UNUSED(decimal_points);
353 return str_val->data()[0];
355 else if constexpr (std::is_same_v<T, std::string_view>)
357 LLFIX_UNUSED(decimal_points);
358 return str_val->to_string_view();
360 else if constexpr (std::is_same_v<T, bool>)
362 LLFIX_UNUSED(decimal_points);
363 return (str_val->data()[0] == FixConstants::FIX_BOOLEAN_TRUE) ? true :
false;
365 else if constexpr (std::is_same_v<T, FixedPoint>)
367 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
373 else if constexpr (std::is_floating_point<T>::value)
375 llfix_assert_msg(decimal_points > 0,
"You have to specify a decimal points value that is greater than zero");
376 return Converters::chars_to_double(str_val->c_str(), str_val->length(), decimal_points);
378 else if constexpr (std::is_integral<T>::value && std::is_signed<T>::value)
380 LLFIX_UNUSED(decimal_points);
381 return Converters::chars_to_int<int>(str_val->c_str(), str_val->length());
383 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint64_t))
385 LLFIX_UNUSED(decimal_points);
386 return Converters::chars_to_unsigned_int<uint64_t>(str_val->c_str(), str_val->length());
388 else if constexpr (std::is_integral<T>::value &&
sizeof(T) ==
sizeof(uint32_t))
390 LLFIX_UNUSED(decimal_points);
391 return Converters::chars_to_unsigned_int<uint32_t>(str_val->c_str(), str_val->length());
395 static_assert(always_false_v<T>,
"get_repeating_group_tag_value_as unsupported type");
400 bool is_tag_value_numeric(uint32_t tag)
const
402 llfix_assert_msg(m_dict.has_key(tag) ==
true,
"You should call has_tag first");
403 llfix_assert_msg(m_dict[tag].generation_id == m_generation_id,
"You should call has_tag first");
404 return m_dict[tag].value->is_numeric();
407 bool validate_count_tag(uint32_t tag, uint32_t& out_reject_message_code)
const
409 return m_repeating_groups.validate_count_tag(tag, out_reject_message_code);
412 Dictionary<uint32_t, IncomingValue>* get_dictionary()
417 uint64_t get_generation_id()
const {
return m_generation_id; }
420 uint64_t m_generation_id = 1;
421 mutable Dictionary<uint32_t, IncomingValue> m_dict;
422 IncomingFixRepeatingGroups<FixStringView> m_repeating_groups;
425 static constexpr
bool always_false_v =
false;
427 IncomingFixMessage(
const IncomingFixMessage& other) =
delete;
428 IncomingFixMessage& operator= (
const IncomingFixMessage& other) =
delete;
429 IncomingFixMessage(IncomingFixMessage&& other) =
delete;
430 IncomingFixMessage& operator=(IncomingFixMessage&& other) =
delete;